【发布时间】:2020-03-15 01:47:34
【问题描述】:
SQL Server:以下存储过程不工作,但 SQL 语句在存储过程之外工作。
CREATE PROCEDURE schema1.dropConstraints
(@schemaName AS nvarchar, @tableName AS nvarchar)
AS
BEGIN
DECLARE @cname nvarchar(80)
DECLARE @sqlStatement nvarchar(100)
DECLARE myCursor CURSOR LOCAL FOR
SELECT constraint_name
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE constraint_schema = @schemaName
AND table_name = @tableName;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO @cname;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sqlStatement = 'ALTER TABLE ' + @schemaName + '.' + @tableName + ' DROP CONSTRAINT ' + @cname;
EXEC sp_executesql @sqlStatement;
FETCH NEXT FROM myCursor INTO @cname;
END;
CLOSE myCursor;
DEALLOCATE myCursor;
END;
调用存储过程
exec schema1.dropConstraints 'schema1', 'Foo';
表Foo 的约束(PK、FK)未被删除。没有错误。
但是在存储过程之外运行代码,它工作正常。
DECLARE @schemaName nvarchar(80) = 'schema1';
DECLARE @tableName nvarchar(80) = 'Foo';
DECLARE @cname nvarchar(80)
DECLARE @sqlStatement nvarchar(100)
DECLARE myCursor CURSOR LOCAL FOR
SELECT constraint_name
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE constraint_schema = @schemaName AND table_name = @tableName;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO @cname;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sqlStatement = 'ALTER TABLE ' + @schemaName + '.' + @tableName + ' DROP CONSTRAINT ' + @cname;
EXEC sp_executesql @sqlStatement;
FETCH NEXT FROM myCursor INTO @cname;
END;
CLOSE myCursor;
DEALLOCATE myCursor;
这行得通。表Foo 的约束(PK、FK)被删除。有什么区别?
登录:sa。
【问题讨论】:
-
虽然可能不是问题的原因,但
OPEN和CLOSE和DEALLOCATE语句之间的游标名称不一致(myCursorvsc)。 -
旁注:对于类似模式或表名的标识,请使用
sysname。不要在查询字符串中使用不带引号的标识符。它是专门用于对象标识符的特殊数据类型。并使用quotename()引用它们。否则,如果为您的程序提供的标识符不是简单的标识符,甚至是恶意格式错误从而启用注入,您就会遇到问题。 -
您没有为
nvarchar数据类型参数指定长度。默认长度为 1,因此指定的值被截断。就个人而言,我会像建议的@stickybit 一样使用sysname,它是nvarchar(128)的同义词,并与SQL Server 对象和列名对齐。 -
@EdHarper 光标名称已修复。
-
添加
PRINT @sqlStatement以检查 NVARCHAR 长度是否是问题
标签: sql-server stored-procedures