查找并更新具有唯一约束的列中保存的重复值? - 消息 402 添加运算符中的数据类型不兼容

问题描述 投票:0回答:1

我需要创建一个 SQL Server 查询来清理旧数据库,方法是确保具有唯一约束的列中的所有非唯一值都更新为唯一。

为此,我想找到数据库中具有唯一约束的所有列。然后遍历这些列中的所有值以查找任何非唯一值。最后,考虑在任何非唯一值的末尾添加后缀。当使用后缀时,它会增加 1。

对于所有重复项,需要将表、列、旧的非唯一值和新的唯一值写入控制台。

对我来说,似乎我需要使用动态 SQL 来实现这一点。

有更好的方法吗?

这是我目前拥有的:

DECLARE @tableName NVARCHAR(255)
DECLARE @columnName NVARCHAR(255)
DECLARE @sql NVARCHAR(MAX)

DECLARE uniqueColumns CURSOR FOR
SELECT
    cu.TABLE_NAME,
    cu.COLUMN_NAME
FROM
    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu
    JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
WHERE
    tc.CONSTRAINT_TYPE = 'UNIQUE'

OPEN uniqueColumns

FETCH NEXT FROM uniqueColumns INTO @tableName, @columnName

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = N'
        WITH DuplicatesCTE AS (
            SELECT                
                ColumnNameString AS ColumnName,
                ColumnNameString AS OriginalValue,
                ColumnNameString + ''_'' + CAST(ROW_NUMBER() OVER (PARTITION BY ColumnNameString ORDER BY (SELECT 1)) AS NVARCHAR(MAX)) AS NewValue
            FROM TableNameString
            WHERE ColumnNameString IN (
                SELECT ColumnNameString
                FROM TableNameString
                GROUP BY ColumnNameString
                HAVING COUNT(*) > 1
            )
        )
        UPDATE DuplicatesCTE
        SET OriginalValue = NewValue
        OUTPUT INSERTED.ColumnName, INSERTED.NewValue
    ';

    SET @sql = REPLACE(@sql, 'TableNameString', QUOTENAME(@tableName))
    SET @sql = REPLACE(@sql, 'ColumnNameString', QUOTENAME(@columnName))

    --EXEC sp_executesql @sql
    PRINT @sql

    FETCH NEXT FROM uniqueColumns INTO @tableName, @columnName
END

CLOSE uniqueColumns
DEALLOCATE uniqueColumns

我收到此错误:

消息 402,第 16 级,状态 1,第 6 行
数据类型 uniqueidentifier 和 varchar 在添加运算符中不兼容。

如果我打印

@sql
而不是执行它,我会得到以下 SQL:

WITH DuplicatesCTE AS (
    SELECT                
        [AdminRoleId] AS ColumnName,
        [AdminRoleId] AS OriginalValue,
        [AdminRoleId] + '_' + CAST(ROW_NUMBER() OVER (PARTITION BY [AdminRoleId] ORDER BY (SELECT 1)) AS NVARCHAR(MAX)) AS NewValue
    FROM [AdminRoleModules]
    WHERE [AdminRoleId] IN (
        SELECT [AdminRoleId]
        FROM [AdminRoleModules]
        GROUP BY [AdminRoleId]
        HAVING COUNT(*) > 1
    )
)
UPDATE DuplicatesCTE
SET OriginalValue = NewValue

我也遇到同样的错误:

消息 402,第 16 级,状态 1,第 5 行
数据类型 uniqueidentifier 和 varchar 在添加运算符中不兼容。

sql sql-server dynamic-sql unique-constraint database-cursor
1个回答
0
投票

看起来我的动态 SQL 中有几个语法错误。此外,我忘记只在字符串上运行它,而不是在主键或外键上运行。这些问题已在以下 SQL 中得到修复:

DECLARE @tableName NVARCHAR(255)
DECLARE @columnName NVARCHAR(255)
DECLARE @sql NVARCHAR(MAX)

DECLARE uniqueColumns CURSOR FOR
SELECT
    cu.TABLE_NAME,
    cu.COLUMN_NAME
FROM
    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu
    JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc ON cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
    JOIN INFORMATION_SCHEMA.COLUMNS col ON cu.COLUMN_NAME = col.COLUMN_NAME AND cu.TABLE_NAME = col.TABLE_NAME
WHERE
    tc.CONSTRAINT_TYPE = 'UNIQUE'
    AND col.DATA_TYPE = 'NVARCHAR'

OPEN uniqueColumns

FETCH NEXT FROM uniqueColumns INTO @tableName, @columnName

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @sql = N'
        WITH DuplicatesCTE AS (
            SELECT                
                ColumnNameString AS ColumnName,
                ColumnNameString AS OriginalValue,
                (ColumnNameString + ''_'' + CAST(ROW_NUMBER() OVER (PARTITION BY ColumnNameString ORDER BY (SELECT 1)) AS NVARCHAR(MAX))) AS NewValue
            FROM TableNameString
            WHERE ColumnNameString IN (
                SELECT ColumnNameString
                FROM TableNameString
                GROUP BY ColumnNameString
                HAVING COUNT(*) > 1
            )
        )
        UPDATE DuplicatesCTE
        SET OriginalValue = NewValue
        OUTPUT INSERTED.ColumnName--, INSERTED.NewValue
    ';

    SET @sql = REPLACE(@sql, 'TableNameString', QUOTENAME(@tableName))
    SET @sql = REPLACE(@sql, 'ColumnNameString', QUOTENAME(@columnName))

    EXEC sp_executesql @sql
    --PRINT @sql

    FETCH NEXT FROM uniqueColumns INTO @tableName, @columnName
END

CLOSE uniqueColumns
DEALLOCATE uniqueColumns

然而,这在输出表名、列名、旧值和新值方面仍然存在不足,因此可以审核更改。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.