[英]Finding a Primary Key Constraint on the fly in SQL Server 2005
我有以下 SQL:
ALTER TABLE dbo.PS_userVariables DROP CONSTRAINT PK_PS_userVariables;
ALTER TABLE dbo.PS_userVariables ADD PRIMARY KEY (varnumber, subjectID, userID, datasetID, listid, userVarTitle);
由於我有多個環境,因此 PK_PS_userVariables 約束名稱在我的不同數據庫上是不同的。 如何編寫一個獲取該名稱的腳本,然后將其添加到我的腳本中?
雖然典型的最佳實踐是始終明確命名您的約束,但您可以從目錄視圖中動態獲取它們:
DECLARE @table NVARCHAR(512), @sql NVARCHAR(MAX);
SELECT @table = N'dbo.PS_userVariables';
SELECT @sql = 'ALTER TABLE ' + @table
+ ' DROP CONSTRAINT ' + name + ';'
FROM sys.key_constraints
WHERE [type] = 'PK'
AND [parent_object_id] = OBJECT_ID(@table);
EXEC sp_executeSQL @sql;
ALTER TABLE dbo.PS_userVariables ADD CONSTRAINT ...
SELECT
A.TABLE_NAME,
A.CONSTRAINT_NAME,
B.COLUMN_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS A,
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE B
WHERE
CONSTRAINT_TYPE = 'PRIMARY KEY'
AND A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
ORDER BY
A.TABLE_NAME
參考:Pinal Dave @ http://blog.sqlauthority.com/2008/09/06/sql-server-find-primary-key-using-sql-server-management-studio/
DECLARE @TableName varchar(128)
DECLARE @IndexName varchar(128)
DECLARE @Command varchar(1000)
SET @TableName = 'PS_userVariables'
SELECT @IndexName = si.name
FROM sys.tables st
JOIN sys.indexes si ON st.object_id = si.object_id
WHERE st.name = @TableName
AND si.is_primary_key = 1
SET @Command = 'ALTER TABLE dbo.' + QUOTENAME(@Tablename) + ' DROP CONSTRAINT ' + QUOTENAME(@IndexName) + ';
ALTER TABLE dbo.' + QUOTENAME(@Tablename) + ' ADD PRIMARY KEY (varnumber, subjectID, userID, datasetID, listid, userVarTitle);'
我的用例是更新 Entity Framework 6 生成的主鍵約束名稱以匹配 Entity Framework Core 的主鍵命名約定。
由於 EF 使用遷移,我創建了一個Up
和Down
遷移腳本,並創建了一個臨時的長壽命表來存儲新舊約束名稱,以便我可以在需要時回滾。
這是我用來更新主鍵約束名稱的 SQL:
-- create a temporary long-lived table
-- it can be deleted when rollback is no longer needed
CREATE TABLE dbo.__OldPrimaryKeyConstraintNames (
SchemaName NVARCHAR(128) NOT NULL DEFAULT 'dbo',
TableName NVARCHAR(128) NOT NULL,
OldPrimaryKeyConstraintName NVARCHAR(128) NOT NULL,
NewPrimaryKeyConstraintName NVARCHAR(128) NOT NULL
);
-- create a temporary table to hold the data for the script
DECLARE @tbl TABLE (SchemaName NVARCHAR(3), TableName NVARCHAR(128), PrimaryKeyConstraintName NVARCHAR(128));
-- get all primary key constraint names as well as it's schema and table
INSERT INTO @tbl
SELECT SCHEMA_NAME(pk.schema_id), t.name, pk.name
FROM sys.key_constraints pk
INNER JOIN sys.objects t on t.object_id = pk.parent_object_id
WHERE pk.type = 'PK'
-- row count used for iterating through @tbl
DECLARE @RowCount INT = (SELECT COUNT(*) FROM @tbl);
-- variables used when used for iterating through @tbl
DECLARE @SchemaName NVARCHAR(128)
DECLARE @TableName NVARCHAR(128)
DECLARE @OldPrimaryKeyConstraintName NVARCHAR(128)
DECLARE @NewPrimaryKeyConstraintName NVARCHAR(128)
DECLARE @RenameSql NVARCHAR(MAX)
WHILE @RowCount > 0 BEGIN
-- get the primary key constraint name, schema, and table name for this iteration
SELECT @SchemaName = SchemaName, @TableName = TableName, @OldPrimaryKeyConstraintName = PrimaryKeyConstraintName, @NewPrimaryKeyConstraintName = CONCAT('PK_', TableName)
FROM @tbl
ORDER BY PrimaryKeyConstraintName DESC OFFSET @RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
-- store the old and new primary key constraint names
INSERT __OldPrimaryKeyConstraintNames (SchemaName, TableName, OldPrimaryKeyConstraintName, NewPrimaryKeyConstraintName)
VALUES (@SchemaName, @TableName, @OldPrimaryKeyConstraintName, @NewPrimaryKeyConstraintName)
-- perform the rename
SET @RenameSql = 'sp_rename ' + '''' + @SchemaName + '.' + QUOTENAME(@OldPrimaryKeyConstraintName) + '''' + ', ' + '''' + @NewPrimaryKeyConstraintName + ''''
EXEC sp_executeSQL @RenameSql
-- move to the next row
SET @RowCount -= 1;
END
運行此腳本后, dbo.__OldPrimaryKeyConstraintNames
應填充新舊約束名稱。
這使我們可以在出於任何原因需要時恢復重命名。
這是我用來還原主鍵約束名稱的 SQL:
-- create a temporary table to hold the data for the script
DECLARE @tbl TABLE (SchemaName NVARCHAR(3), OldPrimaryKeyConstraintName NVARCHAR(128), NewPrimaryKeyConstraintName NVARCHAR(128));
-- get the old and new constraint names as well as it's schema and table name
INSERT INTO @tbl
SELECT SchemaName, OldPrimaryKeyConstraintName, NewPrimaryKeyConstraintName
FROM dbo.__OldPrimaryKeyConstraintNames
-- row count used for iterating through @tbl
DECLARE @RowCount INT = (SELECT COUNT(*) FROM @tbl);
-- variables used when used for iterating through @tbl
DECLARE @SchemaName NVARCHAR(128)
DECLARE @TableName NVARCHAR(128)
DECLARE @OldPrimaryKeyConstraintName NVARCHAR(128)
DECLARE @NewPrimaryKeyConstraintName NVARCHAR(128)
DECLARE @RenameSql NVARCHAR(MAX)
WHILE @RowCount > 0 BEGIN
-- get the old and new constraint name and it's schema for this iteration
SELECT @SchemaName = SchemaName, @OldPrimaryKeyConstraintName = OldPrimaryKeyConstraintName, @NewPrimaryKeyConstraintName = NewPrimaryKeyConstraintName
FROM @tbl
ORDER BY OldPrimaryKeyConstraintName DESC OFFSET @RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
-- revert the rename
SET @RenameSql = 'sp_rename ' + '''' + @SchemaName + '.' + QUOTENAME(@NewPrimaryKeyConstraintName) + '''' + ', ' + '''' + @OldPrimaryKeyConstraintName + ''''
SELECT @RenameSql
EXEC sp_executeSQL @RenameSql
-- move to the next row
SET @RowCount -= 1;
END
-- drop the temporary long-lived table as it is not required
DROP TABLE IF EXISTS dbo.__OldPrimaryKeyConstraintNames
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.