如何对删除表的T-SQL存储过程进行参数化?
我想要一个简单的存储过程来删除表。这是我的第一次尝试:如何对删除表的T-SQL存储过程进行参数化?,sql,sql-server-2005,tsql,Sql,Sql Server 2005,Tsql,我想要一个简单的存储过程来删除表。这是我的第一次尝试: CREATE PROC bsp_susf_DeleteTable (@TableName char) AS IF EXISTS (SELECT name FROM sysobjects WHERE name = @TableName) BEGIN DROP TABLE @TableName END 当我在MS Query Analyzer中解析此项时,我得到以下错误: Server: Msg 170, Level 15, State 1,
CREATE PROC bsp_susf_DeleteTable (@TableName char)
AS
IF EXISTS (SELECT name FROM sysobjects WHERE name = @TableName)
BEGIN
DROP TABLE @TableName
END
当我在MS Query Analyzer中解析此项时,我得到以下错误:
Server: Msg 170, Level 15, State 1, Procedure bsp_susf_DeleteTable, Line 6
Line 6: Incorrect syntax near '@TableName'.
哪种类型有意义,因为单个表的常规SQL是:
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'tbl_XYZ')
BEGIN
DROP TABLE tbl_XYZ
END
注意tbl_XYZ的第一个实例(在WHERE子句中)周围有单引号,而DROP语句中的第二个实例没有。如果我使用一个变量(@TableName),那么我就不需要进行这种区分
那么,是否可以创建一个存储过程来执行此操作?或者如果存在,我必须复制。。。无处不在?您必须使用EXEC以字符串形式执行该查询。换句话说,当您传入表名时,定义一个varchar并分配查询和表名,然后执行您创建的变量 编辑:但是,我不建议这样做,因为有人可能传入sql而不是表名,从而导致各种各样的问题。有关更多信息,请参阅Sql注入 最好是在客户端为此创建一个参数化查询。例如,在C#中,我会做如下操作:
// EDIT 2: on second thought, ignore this code; it probably won't work
SqlCommand sc = new SqlCommand();
sc.Connection = someConnection;
sc.CommandType = Command.Text;
sc.CommandText = "drop table @tablename";
sc.Parameters.AddWithValue("@tablename", "the_table_name");
sc.ExecuteNonQuery();
您应该能够使用动态sql:
declare @sql varchar(max)
if exists (select name from sysobjects where name = @TableName)
BEGIN
set @sql = 'drop table ' + @TableName
exec(@sql)
END
希望这有帮助
更新:是的,你可以把@sql缩小,这只是一个简单的例子。另外请注意关于SQL注入攻击的其他评论我个人对此非常谨慎。如果您觉得出于管理目的需要此文件,请确保执行此文件的权限非常有限。此外,我将让proc将表名和日期以及执行它的用户复制到日志记录表中。这样至少你会知道是谁把桌子掉错了。你可能还需要其他保护措施。例如,您可能希望指定某些无法使用此过程删除的表 此外,这并不是在所有情况下都适用于所有表。不能删除与外键关联的表 在任何情况下,我都不允许用户或任何不是数据库管理员的人执行此过程。如果您有一个用户可以删除表格的系统设计,那么您的设计很可能存在严重错误,应该重新思考
另外,除非您有非常非常好的备份计划,并且有从备份中恢复的经验,否则不要使用此过程。Make@SQL nvarchar(max),因为表名是nvarchar。(实际上是sysname,但相当于nvarchar(一些数字,可能是128?)您还应该将@TableName转义为方括号。SQL Server有一个命令可以为您执行此操作。Set@SQL='drop table'+QuoteName(@TableName);老实说,如果存储过程的目的是删除传入的任意表,那么SQL错误攻击会更糟糕吗?我的意思是,如果可以在不需要黑客攻击的情况下删除数据库中的任何表,为什么还要逃避sring呢?顺便说一句,这()这就是为什么您需要担心Sql注入的原因。这些都是很好的观点。我的情况是,这些都不是问题。我们有一个生产数据库,它会在一夜之间复制,形成我们的报告数据库。我们对这个副本运行报告,以生成包含派生数据(没有外键)的表。我们只删除这些派生表。但如果我们意外地丢弃了某些内容,这并不重要。