【发布时间】:2013-10-15 13:55:39
【问题描述】:
我正在尝试构建一个脚本,该脚本将删除特定架构中的所有外键(我正在创建一个新数据库,该数据库需要脚本化到其他几个位置、一个测试环境和一个生产环境)。拥有这三个独立环境的最简单方法是在“开发”上使用我的“CREATE”脚本,然后在以后通过我们的其他环境进行分阶段。这要求(作为一种可能的解决方案)“CREATE”脚本的开头是一种If Exists(...) DROP...。
我已经解决了我遇到的问题,但希望有人可以解释我所看到的行为(见下文)。
这段代码有效(我得到一条语句,它把所有记录都作为自己的 SQL 语句):
DECLARE @SQL VARCHAR(MAX) = ''
DECLARE @Schema VARCHAR(100) = 'SchemaName'
SELECT
@SQL = @SQL
+ 'ALTER TABLE ' + tpa.name + CHAR(13) + CHAR(10)
+ CHAR(9) + 'DROP CONSTRAINT ' + fk.name +';' + CHAR(13) + CHAR(10)
FROM
sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fkc
ON fkc.constraint_object_id = fk.object_id
JOIN sys.tables AS tpa
ON fk.parent_object_id = tpa.object_id
JOIN sys.columns AS cpa
ON tpa.object_id = cpa.object_id AND
fkc.parent_column_id = cpa.column_id
JOIN sys.tables AS tref
ON fkc.parent_object_id = tref.object_id
JOIN sys.columns AS cref
ON tref.object_id = cref.object_id AND
fkc.referenced_column_id = cref.column_id
WHERE
SCHEMA_NAME(fk.schema_id) = @Schema
PRINT @SQL
这段代码不起作用(它只返回记录集的最后一行):
DECLARE @SQL VARCHAR(MAX) = ''
DECLARE @Schema VARCHAR(100) = 'SchemaName'
SELECT
@SQL = @SQL
+ 'ALTER TABLE ' + tpa.name + CHAR(13) + CHAR(10)
+ CHAR(9) + 'DROP CONSTRAINT ' + fk.name +';' + CHAR(13) + CHAR(10)
FROM
sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fkc
ON fkc.constraint_object_id = fk.object_id
JOIN sys.tables AS tpa
ON fk.parent_object_id = tpa.object_id
JOIN sys.columns AS cpa
ON tpa.object_id = cpa.object_id AND
fkc.parent_column_id = cpa.column_id
JOIN sys.tables AS tref
ON fkc.parent_object_id = tref.object_id
JOIN sys.columns AS cref
ON tref.object_id = cref.object_id AND
fkc.referenced_column_id = cref.column_id
WHERE
SCHEMA_NAME(fk.schema_id) = @Schema
ORDER BY
OBJECT_NAME(fk.parent_object_id)
,OBJECT_NAME(fk.referenced_object_id)
,fk.name
PRINT @SQL
违规行似乎是ORDER BY 中的OBJECT_NAME(fk.referenced_object_id),因为注释掉解决了问题,但我不明白为什么它会失败。我的怀疑是某些东西在本质上或某些东西上做一个小组。
即使包括 ORDER BY 中的所有列似乎也无济于事:
DECLARE @SQL VARCHAR(MAX) = ''
DECLARE @Schema VARCHAR(100) = 'UserMgmt'
SELECT
@SQL = @SQL
+ 'ALTER TABLE ' + tpa.name + CHAR(13) + CHAR(10)
+ CHAR(9) + 'DROP CONSTRAINT ' + fk.name +';' + CHAR(13) + CHAR(10)
+ '--' + OBJECT_NAME(fk.referenced_object_id) + ', ' + OBJECT_NAME(fk.parent_object_id) + CHAR(13) + CHAR(10)
FROM
sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fkc
ON fkc.constraint_object_id = fk.object_id
JOIN sys.tables AS tpa
ON fk.parent_object_id = tpa.object_id
JOIN sys.columns AS cpa
ON tpa.object_id = cpa.object_id AND
fkc.parent_column_id = cpa.column_id
JOIN sys.tables AS tref
ON fkc.parent_object_id = tref.object_id
JOIN sys.columns AS cref
ON tref.object_id = cref.object_id AND
fkc.referenced_column_id = cref.column_id
WHERE
SCHEMA_NAME(fk.schema_id) = @Schema
ORDER BY
OBJECT_NAME(fk.parent_object_id)
,OBJECT_NAME(fk.referenced_object_id)
,fk.name
PRINT @SQL
但是,更改引用表的 JOIN 语句确实可以做到这一点:
DECLARE @SQL VARCHAR(MAX) = ''
DECLARE @Schema VARCHAR(100) = 'UserMgmt'
SELECT
@SQL = @SQL
+ 'ALTER TABLE ' + tpa.name + CHAR(13) + CHAR(10)
+ CHAR(9) + 'DROP CONSTRAINT ' + fk.name +';' + CHAR(13) + CHAR(10)
+ '--' + OBJECT_NAME(fk.referenced_object_id) + ', ' + OBJECT_NAME(fk.parent_object_id) + CHAR(13) + CHAR(10)
FROM
sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fkc
ON fkc.constraint_object_id = fk.object_id
JOIN sys.tables AS tpa
ON fk.parent_object_id = tpa.object_id
JOIN sys.columns AS cpa
ON tpa.object_id = cpa.object_id AND
fkc.parent_column_id = cpa.column_id
JOIN sys.tables AS tref
ON fk.referenced_object_id = tref.object_id
JOIN sys.columns AS cref
ON tref.object_id = cref.object_id AND
fkc.referenced_column_id = cref.column_id
WHERE
SCHEMA_NAME(fk.schema_id) = @Schema
ORDER BY
OBJECT_NAME(fk.parent_object_id)
,OBJECT_NAME(fk.referenced_object_id)
,fk.name
PRINT @SQL
谁能解释这种行为?
【问题讨论】:
-
这里的 order by 仍然会导致它失败,即使在 select 语句中指定了列。但是,更改 JOIN 子句似乎确实允许 ORDER BY 工作。查看我的编辑。
标签: sql-server tsql sql-order-by string-concatenation