特定のスキーマ内のすべての外部キーを削除するスクリプトを作成しようとしていました (他のいくつかの場所、テスト環境、および運用環境にスクリプトを作成する必要がある新しいデータベースの作成に取り組んでいます)。これら 3 つの個別の環境を作成する最も簡単な方法は、"開発" で "CREATE" スクリプトを使用し、後日、他の環境を介してステージングすることです。これには、(考えられる解決策の 1 つとして)「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
問題のある行はOBJECT_NAME(fk.referenced_object_id)
、ORDER BY
コメントアウトすると問題が解決するようですが、なぜ失敗するのかわかりません。私の疑いは、何かが本質的にまたは何かによってグループをやっているということです。
のすべての列を含めても、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
誰でもこの動作を説明できますか?