4

我想知道是否可以创建一个将值插入动态表的存储过程。

我试过

create procedure asd
(@table varchar(10), @id int)
as
begin
    insert into @table values (@id)
end

也定义@table为表变量

谢谢你的帮助!

4

3 回答 3

2

这可能对你有用。

CREATE PROCEDURE asd
(@table nvarchar(10), @id int)
AS
BEGIN
    DECLARE @sql nvarchar(max)
    SET @sql = 'INSERT INTO ' + @table + ' (id) VALUES (' + CAST(@id AS nvarchar(max)) + ')'
    EXEC sp_executesql @sql
END

在此处查看更多信息:http: //msdn.microsoft.com/de-de/library/ms188001.aspx

于 2013-03-23T12:45:00.867 回答
1

您需要使用动态 SQL。

要创建动态 SQL,您需要将查询构建为字符串。使用IF语句和其他逻辑来添加变量等。

声明一个文本变量并使用它来连接你想要的 SQL。

然后,您可以使用EXEC命令执行此代码

例子:

DECLARE @SQL VARCHAR(100)
DECLARE @TableOne VARCHAR(20) = 'TableOne'
DECLARE @TableTwo VARCHAR(20) = 'TableTwo'
DECLARE @SomeInt INT

SET @SQL = 'INSERT INTO '

IF (@SomeInt = 1)
    SET @SQL = @SQL + @TableOne

IF (@SomeInt = 2)
    SET @SQL = @SQL + @TableTwo

SET @SQL = @SQL + ' VALUES....etc'

EXEC (@SQL)

但是,使用此方法时您真正应该注意的是一个称为SQL 注入的安全问题。

你可以在这里阅读。

防止 SQL 注入的一种方法是在将变量传递给 SQL-Server 之前在代码中对其进行验证。

另一种方法(或者可能在推测中最好使用)不是使用EXEC命令,而是使用名为sp_executesql.

详细信息可以在这里找到,使用说明在这里

您必须稍微不同地构建您的 SQL,并将您的参数作为参数以及@SQL 传递给存储过程。

于 2013-03-23T13:35:41.503 回答
1

是的,要直接实现这一点,您需要动态 SQL,正如其他人所建议的那样。但是,我也同意@Tomalak 的评论,即尝试这种普遍性可能会导致代码安全性降低或效率降低(或两者兼而有之)。

如果你觉得你必须有这种级别的动态性,你可以尝试下面的方法,虽然比普通的动态 SQL 需要更多的努力,但与后者几乎相同,但没有刚才提到的缺点。

这个想法是首先创建所有必要的插入过程,一个用于您要在其中插入这么多此类值的每个表(即,根据您的示例,恰好是一个int值)。统一命名这些过程至关重要,例如使用此模板:目标表的名称TablenameInsert在哪里。Tablename

接下来,创建您的通用插入程序,如下所示:

CREATE PROCEDURE InsertIntValue (
  @TableName sysname,
  @Value int
) 
AS
BEGIN
  DECLARE @SPName sysname;
  SET @SPName = @TableName + 'Insert';
  EXECUTE @SPName @Value;
END;

从手册中可以看出,使用命令调用模块时EXECUTE,可以指定一个变量而不是实际的模块名。在这种情况下,变量应该是字符串类型,并且应该包含要执行的模块的名称。这不是动态 SQL,因为语法不一样。(对于动态 SQL,变量需要用括号括起来。)相反,这本质上是模块名称的参数化,可能是 (Transact-)SQL 中唯一一种本机支持的名称参数化。

就像我说的,这比动态 SQL 需要更多的努力,因为您仍然必须创建这个通用 SP 应该能够调用的所有许多存储过程。然而,结果是,您获得的代码既安全(@SPName服务器仅将变量视为名称,而不是任意 SQL 片段)又高效(调用的实际存储过程已经存在,即它已经存在)编译并有一个查询计划)。

于 2013-03-27T15:52:23.807 回答