将值插入动态表的存储过程

时间:2013-03-23 12:37:11

标签: sql-server tsql

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

我试过

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

还将@table定义为表格var

感谢您的帮助!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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注入的安全问题。

您可以阅读here

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

另一种方法(或者最好用于猜想)不是使用EXEC命令,而是使用名为sp_executesql的内置存储过程。

可以找到详细信息here,使用说明为here

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

答案 2 :(得分:0)

是的,要直接实现这一点,您需要动态SQL,正如其他人所建议的那样。但是,我也同意comment by @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;

可以看到from the manual,当使用EXECUTE命令调用模块时,您可以指定变量而不是实际的模块名称。在这种情况下,变量应该是字符串类型,并且应该包含要执行的模块的名称。这是不是动态SQL,因为语法不一样。 (为了使它成为动态SQL,需要将变量括在括号中。)相反,这实际上是模块名称的参数化,可能是(Transact-)SQL中唯一一种本机支持的名称参数化。

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