【发布时间】:2017-03-17 18:33:20
【问题描述】:
大家好,我正在想办法解决这个问题。我想向我的 C# 程序中的查询发送一个参数,它是我的表的名称。我读到这是不可能的,他们建议您创建一个存储过程来执行此操作。
到目前为止,这是我的代码:
CREATE PROCEDURE _tmpSP
@TableName NVARCHAR(128)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @Sql NVARCHAR(MAX);
SET @Sql = N'SELECT TOP 1 HelpMsg FROM ' + QUOTENAME(@TableName)
EXECUTE sp_executesql @Sql
DROP PROCEDURE [_tmpSP]
END
当我在 Server Management Studio 中执行它时,它会创建 SP,但不会执行该存储过程,也不会删除它。
当我在 Server Management Studio 中运行该 SP 时(右键单击它在可编程性下dbo._tmpSP并选择执行存储过程)并给它表名,它填充然后删除SP。这是我想要无需进行 2 次查询的最终结果。
SP 运行时的 SQL 查询如下(tHelp 是表名):
USE [TTool]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[_tmpSP]
@TableName = N'tHelp'
SELECT 'Return Value' = @return_value
GO
我收到返回的帮助消息,也返回值 0。
如何修改此 SP 才能做到这一点?
【问题讨论】:
-
你为什么要创建一个存储过程,这样你就可以执行一次然后删除它?这根本没有任何意义。为什么需要存储过程?当然,创建程序的脚本不会运行它。
-
@SeanLange 因为我无法做到这一点:SELECT TOP 1 HelpMsg FROM @val1
-
这是什么?一个自毁过程 :) 我原以为查询处理器会拒绝删除它当前正在执行的过程。
-
那是因为你不能参数化对象名称。但说真的,这有什么意义呢?参数化的主要思想之一是防止 sql 注入,而您创建的代码甚至不会假装避免这种情况。事实上,您已经通过使用它来构建一个动态字符串来执行该参数的全部意义。只需创建您的动态字符串并执行它。但请保留引号名称。您甚至可以检查 sys.objects 以确保该值是对象名称。
-
除了这里提出的问题外,还可能存在设计缺陷。 TOP 1 不是确定性的。所以要么这些表每个只包含一行,那么你最好将所有这些帮助文本合并到一个带有一些有意义的键的表中,或者你冒着每次查询运行时读取不同行的风险。
标签: c# sql-server stored-procedures sql-server-2012