我想知道是否可以创建一个将值插入动态表的存储过程。
我试过
create procedure asd
(@table varchar(10), @id int)
as
begin
insert into @table values (@id)
end
还将@table
定义为表格var
感谢您的帮助!
答案 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
的内置存储过程。
您必须以稍微不同的方式构建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的任意片段)且效率高(正在调用的实际存储过程已经存在,即它已经编译并具有查询计划。)