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。
答案 0 :(得分:2)
这些参数数据类型声明中缺少最大字符长度:
CREATE PROCEDURE schema1.dropConstraints
(@schemaName AS nvarchar, @tableName AS nvarchar)
因为默认长度为1,所以提供的值将被静默截断为单个字符,并且结果与预期不符。
确保参数数据类型和长度与引用列的类型匹配是一种很好的做法。对于INFORMATION_SCHEMA
视图,请查阅documentation,您会发现适当的数据类型为nvarchar(128)。我个人喜欢在SQL Server中将sysname
用于标识符类型,这是nvarchar(128)
的同义词。
CREATE PROCEDURE schema1.dropConstraints
@schemaName AS sysname, @tableName AS sysname