我正在尝试创建一个存储过程,以从动态选择的表中删除所有数据。
我使用了此代码,但无法正常工作。有什么建议吗?
CREATE PROCEDURE spDynamicDeleteTable
@table NVARCHAR(100)
AS
BEGIN
DECLARE @Sql NVARCHAR(MAX)
SET @Sql= 'DELETE FROM'+ @table
EXECUTE sp_executesql @Sql
END
答案 0 :(得分:1)
您缺少空格。
Set @Sql= 'Delete from'+ @table
将成为
Delete fromelbat
如果@table = 'elbat'
。那是无效的语法。
在“ from”之后添加一个空格。最好使用quotename()
来防止在不寻常的表名下发生有趣的事情。
Set @Sql= 'Delete from ' + quotename(@table)
更多注意事项:
@table
最好声明为sysname
,而不是nvarchar(100)
。 sysname
是对象名称的额外类型。
请注意,您必须非常小心执行此存储过程的权限,以防止滥用该存储过程删除任意数据。
答案 1 :(得分:1)
这将防止sql注入,并且还允许您将架构作为可选参数提供
ALTER PROCEDURE spDynamicDeleteTable
@table nvarchar(128),
@schema nvarchar(128) = 'dbo'
AS
BEGIN
DECLARE @Sql NVARCHAR(MAX)
SELECT
@Sql= 'DELETE FROM '+ quotename(s.SCHEMA_NAME) + '.'+ quotename(t.NAME)
FROM sys.tables t
CROSS JOIN
[INFORMATION_SCHEMA].[SCHEMATA] s
WHERE
t.NAME = @table
and s.SCHEMA_NAME = @schema
IF @@rowcount = 1
EXECUTE sp_executesql @Sql
ELSE
print 'failed'
END
答案 2 :(得分:0)
首先,对于动态SQL,您要向SQL Injection开放,而您看到的问题是由于缺少其他答案和评论中提到的空间所致。
但是...
虽然您可以执行类似的操作,但在尝试运行它时可能会遇到问题,主要与引用完整性有关。
以这个例子为例:
用户表
UserId | Name
1 | Bob
2 | Jim
UserOrders表
OrderId | UserId
1 | 1
2 | 1
3 | 2
4 | 2
假设您要删除User
表中的所有记录。 User
表可能在UserOrders
中具有相关信息,因此,由于第二个表链接到第一个表的主键,除非所有相关数据,否则您将无法删除第一个表中的记录删除,唯一的方法是级联删除,这将使这种解决方案变得危险。
如果您只关心静态的,未链接的数据,那么它可以工作,但是如果表之间存在关系,则建议不要使用这种解决方案。