Как я упоминаю в своем комментарии, вы можете использовать динамический оператор c для создания операторов. Однако я очень настоятельно предлагаю просмотреть сгенерированный SQL, поэтому я не включаю здесь оператор EXEC sp_executesql
. PRINT
или SELECT
значение @SQL
и сначала проверьте его, а затем выполните необходимые инструкции:
DECLARE @SQL nvarchar(MAX),
@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SET @SQL = STUFF((SELECT @CRLF + @CRLF +
N'ALTER TABLE ' + QUOTENAME(s.[name]) + N'.' + QUOTENAME(t.[name]) + @CRLF +
N'ADD CONSTRAINT ' + QUOTENAME(CONCAT(t.[name],N'_PK')) + N' PRIMARY KEY (' + QUOTENAME(c.[name]) + N');'
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
CROSS APPLY (SELECT TOP 1 *
FROM sys.columns c
WHERE c.object_id = t.object_id
AND c.name LIKE '%id'
ORDER BY c.column_id ASC) c
WHERE NOT EXISTS (SELECT 1
FROM sys.key_constraints k
WHERE k.[type] = 'PK'
AND k.parent_object_id = t.object_id)
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,4,N'');
PRINT @SQL;
Этот предполагает , что первый столбец, как правило, обычно , должен быть PK, и он не будет пытаться создать PK на таблице, в которой он уже есть.