在SQL Server中更改所有表的所有列的排序规则

83

我导入了一个包含一些数据的数据库并与另一个数据库进行比较。

目标数据库的排序规则为Latin1_General_CI_AS,而源数据库的排序规则为SQL_Latin1_General_CP1_CI_AS

我在SQL Server Management Studio中更改了源数据库的整体排序规则为Latin1_General_CI_AS,但内部的表和列仍保留旧的排序规则。

我知道可以使用以下方法更改列:

ALTER TABLE [table] 
ALTER COLUMN [column] VARCHAR(100) COLLATE Latin1_General_CI_AS

但我必须对所有表格和其中的所有列执行此操作。

在开始编写存储过程之前,我要先读取所有类型为varchar的表格和列,并在表格和列游标循环中更改它们...

有人知道是否有更简单的方法,或者唯一的方法是通过存储过程运行脚本来处理所有表格吗?


5
可能是如何将数据库所有列的排序规则更改为统一的的重复问题。 - Damien_The_Unbeliever
谢谢提供链接。看起来那里的答案与我用脚本想到的想法相似。 - YvesR
http://www.codeproject.com/Articles/302405/The-Easy-way-of-changing-Collation-of-all-Database - NullUserException
13个回答

94

由于我没有找到合适的方法,所以我编写了一个脚本来完成这个任务,并在此分享给需要的人。该脚本遍历所有用户表并收集列。如果列类型是任何字符类型,则尝试将其转换为给定的排序规则。

为使此操作生效,列必须无索引和约束。

如果有更好的解决方案,请发布出来!

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table)
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF (@max_length = -1) OR (@max_length > 4000) SET @max_length = 4000;

        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or constraint rely on the column' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO

3
如果你使用模式,你应该将Select [name] from sysobjects 更改为:SELECT sys.schemas.name + '.' + sys.objects.name AS Name FROM sys.objects INNER JOIN sys.schemas ON sys.objects.schema_id = sys.schemas.schema_id WHERE type_desc = 'USER_TABLE' - Tod
这段代码只适用于索引列需要重新创建的情况。如果您添加以下行,则更新您的代码将完美无缺。SET @sql ='ALTER TABLE ['+@table +'] ALTER COLUMN ['+@column_name +'] '+@data_type +'('+CAST(@max_length AS nvarchar(100))+') COLLATE '+@collate - vast
似乎没有更改关键字段! - QMaster

40

所以,我又来了,对答案不满意。我的任务是将JIRA 6.4.x升级到JIRA Software 7.x,并且我遇到了数据库和列排序的问题。

在SQL Server中,如果您不删除主键、外键或索引等约束条件,上面提供的脚本根本不起作用。但它会更改那些没有这些属性的内容。这真的很棘手,因为我不想手动删除所有约束条件并重新创建它们。这个操作可能会出现错误。另一方面,创建一个自动化更改的脚本可能需要很长时间。

因此,我找到了一种使用SQL Management Studio简单进行迁移的方法。以下是该过程:

  • 将数据库重命名为其他名称。例如,我的数据库名是“Jira”,所以我将其重命名为“JiraTemp”。
  • 创建一个名为“Jira”的新数据库,并确保设置正确的排序规则。只需选择页面“选项”并更改排序规则即可。
  • 创建完成后,返回到“JiraTemp”,右键单击它,“任务->生成脚本...”。
    • 选择“脚本整个数据库和所有数据库对象”。
    • 选择“保存到新查询窗口”,然后选择“高级”
    • 更改“服务器版本的脚本”值为所需值
    • 启用“脚本对象级权限”,“脚本所有者”和“脚本全文索引”
    • 将其他所有内容保持不变或根据需要进行个性化设置。
  • 生成脚本后,删除“CREATE DATABASE”部分。将“JiraTemp”替换为“Jira”。
  • 运行脚本。现在,“Jira”数据库的整个数据库结构和权限都已复制。
  • 在复制数据之前,我们需要禁用所有约束条件。在数据库“Jira”中执行以下命令:EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
  • 现在需要传输数据。要这样做,只需右键单击“JiraTemp”,然后选择“任务->导出数据...”
    • 选择OLE DB Provider for SQL Server作为数据源和目标。
    • 源数据库是“JiraTemp”
    • 目标数据库是“Jira”
    • 服务器名称在技术上对于源和目标是相同的(除非您已在另一台服务器上创建了数据库)。
    • 选择“从一个或多个表或视图复制数据”
    • 选择除视图外的所有表。然后,在仍然突出显示时,单击“编辑映射”。选中“启用标识插入”
    • 单击确定,下一步,然后完成
  • 数据传输可能需要一段时间。完成后,请执行以下命令以重新启用所有约束条件:exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

完成后,我重新启动了 JIRA,我的数据库字符集排序正常了。希望能对很多人有所帮助!


1
针对那些升级到7.x系列的JIRA用户,我发现更容易的方法是进行XML备份,删除数据库,使用正确的排序规则重新创建数据库,然后从XML导入。请参阅https://confluence.atlassian.com/adminjiraserver072/switching-databases-828787577.html。 - trebor
1
我遇到了与pkExec相同的问题(代码页差异)。作为解决方法,我使用了以下脚本:EXEC sp_msforeachtable "PRINT 'INSERT INTO <new_db_name>.? SELECT * FROM ?;'" 然后执行插入操作。我希望这能帮助某些人节省时间... - Pecan
你用的 SQL Server 版本是哪个呢? - David
在尝试将此用于转换Blackbaud Raiser's Edge数据库时出现了一些问题,包括Windows NT用户或组未找到,相关的“无法添加主体,因为它不存在或您没有权限”,使用SAFE或EXTERNAL_ACCESS选项创建或更改程序集...失败,因为'clr strict security'选项...,找不到程序集...,由于先前的错误,CREATE SCHEMA失败等。 - Joe Murray
虽然还有几百个错误,但表已经创建成功了。数据迁移也得以实现。 - Joe Murray
显示剩余3条评论

17

固定长度问题nvarchar并添加NULL/NOT NULL

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
DECLARE @is_Nullable bit;
DECLARE @null nvarchar(25);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
        , c.is_nullable
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table)
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    WHILE @@FETCH_STATUS = 0
    BEGIN

        IF (@max_length = -1) SET @max_length = 4000;
        set @null=' NOT NULL'
        if (@is_nullable = 1) Set @null=' NULL'
        if (@Data_type='nvarchar') set @max_length=cast(@max_length/2 as bigint)
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + rtrim(@column_name) + '] ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) +  ') COLLATE ' + @collate + @null
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or contraint rely on the column ' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_Nullable

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO

1
使用 index_columns 进行连接,而不使用索引实际上会导致列重复;还可以使用过滤器来查找只需要转换的列(c.collation_name <> @collate)。 - Kodak

6
我对这个脚本做了一点小修改。
DECLARE @collate nvarchar(100);
DECLARE @table sysname;
DECLARE @schema sysname;
DECLARE @objectId int;
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);
DECLARE @is_Nullable bit;
DECLARE @null nvarchar(25);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT tbl.TABLE_SCHEMA,[name],obj.id
FROM sysobjects as obj
inner join INFORMATION_SCHEMA.TABLES as tbl
on obj.name = tbl.TABLE_NAME
WHERE OBJECTPROPERTY(obj.id, N'IsUserTable') = 1

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @schema, @table, @objectId;

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE local_change_cursor CURSOR FOR
    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , c.max_length
        , c.column_id
        , c.is_nullable
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = @objectId
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF (@max_length = -1) SET @max_length = 4000;
        set @null=' NOT NULL'
        if (@is_nullable = 1) Set @null=' NULL'
        if (@Data_type='nvarchar') set @max_length=cast(@max_length/2 as bigint)
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' + @schema + '.' + @table + ' ALTER COLUMN [' + rtrim(@column_name) + '] ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) +  ') COLLATE ' + @collate + @null
            PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR: Some index or contraint rely on the column ' + @column_name + '. No conversion possible.'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_Nullable

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @schema,@table,@objectId

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

GO

3
你能告诉我,你做了哪些更改吗?不管怎样,我已经成功地使用了你的脚本。所以谢谢你。 - Uwe Keim

5

我有一个简单的解决方案,可以帮助您完成这个任务。

  1. 创建一个新的数据库,并设置新的排序规则。
  2. 以脚本模式导出原始数据库的数据。
  3. 使用脚本将内容导入到新的数据库中(将USE语句重命名为新的数据库名称)。

但是,如果您的数据库具有触发器、存储过程或类似功能,则需要格外小心,因为这些功能不仅仅涉及数据和表。


4

固定长度问题nvarchar(包括max),包含文本并添加NULL / NOT NULL。

USE [put your database name here];

begin tran

DECLARE @collate nvarchar(100);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length int;
DECLARE @max_length_str nvarchar(100);
DECLARE @is_nullable bit;
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'Latin1_General_CI_AS';

DECLARE local_table_cursor CURSOR FOR

SELECT [name]
FROM sysobjects
WHERE OBJECTPROPERTY(id, N'IsUserTable') = 1
ORDER BY [name]

OPEN local_table_cursor
FETCH NEXT FROM local_table_cursor
INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE local_change_cursor CURSOR FOR

    SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
        , c.name column_name
        , t.Name data_type
        , col.CHARACTER_MAXIMUM_LENGTH
        , c.column_id
        , c.is_nullable
    FROM sys.columns c
    JOIN sys.types t ON c.system_type_id = t.system_type_id
    JOIN INFORMATION_SCHEMA.COLUMNS col on col.COLUMN_NAME = c.name and c.object_id = OBJECT_ID(col.TABLE_NAME)
    LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
    LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id = OBJECT_ID(@table) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%') 
    AND c.collation_name <> @collate
    ORDER BY c.column_id

    OPEN local_change_cursor
    FETCH NEXT FROM local_change_cursor
    INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    WHILE @@FETCH_STATUS = 0
    BEGIN

        set @max_length_str = @max_length
        IF (@max_length = -1) SET @max_length_str = 'max'
        IF (@max_length > 4000) SET @max_length_str = '4000'

        BEGIN TRY
            SET @sql =
            CASE 
                WHEN @data_type like '%text%' 
                THEN 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + ' COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END
                ELSE 'ALTER TABLE ' + @table + ' ALTER COLUMN [' + @column_name + '] ' + @data_type + '(' + @max_length_str + ') COLLATE ' + @collate + ' ' + CASE WHEN @is_nullable = 0 THEN 'NOT NULL' ELSE 'NULL' END
            END
            --PRINT @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR (' + @table + '): Some index or constraint rely on the column ' + @column_name + '. No conversion possible.'
          --PRINT @sql
        END CATCH

        FETCH NEXT FROM local_change_cursor
        INTO @row_id, @column_name, @data_type, @max_length, @column_id, @is_nullable

    END

    CLOSE local_change_cursor
    DEALLOCATE local_change_cursor

    FETCH NEXT FROM local_table_cursor
    INTO @table

END

CLOSE local_table_cursor
DEALLOCATE local_table_cursor

commit tran

GO

注意:如果您只需要更改某些特定排序规则,请使用以下条件:

WHERE c.object_id = OBJECT_ID(@table) AND (t.Name LIKE '%char%' OR t.Name LIKE '%text%') 
    AND c.collation_name = 'collation to change'

例如:不要这样写:AND c.collation_name <> @collate

在我的情况下,我已经正确/指定了一些列的排序规则,并且不想更改它们。


2

抱歉晚来一步,但这是我的答案——为具有模式和有趣列名和表名的表提供支持。是的,我有其中一些。

SELECT 
    'ALTER TABLE [' +  TABLE_SCHEMA + '].[' + TABLE_NAME  
    + '] ALTER COLUMN [' + COLUMN_NAME + '] ' + DATA_TYPE 
    + '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS nvarchar(100)) 
    + ') COLLATE ' + 'Latin1_General_CI_AS' 
    + CASE WHEN IS_NULLABLE = 'YES' THEN ' NULL' ELSE ' NOT NULL' END 
FROM 
    INFORMATION_SCHEMA.COLUMNS 
WHERE 
    DATA_TYPE like '%char'

需要添加一个用于处理最大值的CHARACTER_MAXIMUM_LENGTH的情况,但除此之外,这个程序已经完成了它的工作。 - FAB

1
以下脚本将与最新的类型(如(MAX),IMAGE等)一起使用表模式。根据您的需求在此行上更改排序类型(SET @collate = 'DATABASE_DEFAULT';)。

SQL脚本如下:

BEGIN
DECLARE @collate nvarchar(100);
declare @schema nvarchar(255);
DECLARE @table nvarchar(255);
DECLARE @column_name nvarchar(255);
DECLARE @column_id int;
DECLARE @data_type nvarchar(255);
DECLARE @max_length varchar(100);
DECLARE @row_id int;
DECLARE @sql nvarchar(max);
DECLARE @sql_column nvarchar(max);

SET @collate = 'DATABASE_DEFAULT';

DECLARE tbl_cursor CURSOR FOR SELECT (s.[name])schemaName, (o.[name])[tableName]
FROM sysobjects sy 
INNER JOIN sys.objects  o on o.name = sy.name
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE OBJECTPROPERTY(sy.id, N'IsUserTable') = 1

OPEN tbl_cursor FETCH NEXT FROM tbl_cursor INTO @schema,@table

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE tbl_cursor_changed CURSOR FOR
        SELECT ROW_NUMBER() OVER (ORDER BY c.column_id) AS row_id
            , c.name column_name
            , t.Name data_type
            , c.max_length
            , c.column_id
        FROM sys.columns c
        JOIN sys.types t ON c.system_type_id = t.system_type_id
        LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
        LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
    WHERE c.object_id like OBJECT_ID(@schema+'.'+@table)
    ORDER BY c.column_id


    OPEN tbl_cursor_changed 
     FETCH NEXT FROM tbl_cursor_changed
    INTO @row_id, @column_name, @data_type, @max_length, @column_id



    WHILE @@FETCH_STATUS = 0
    BEGIN
    IF (@max_length = -1) SET @max_length = 'MAX';
        IF (@data_type LIKE '%char%')
        BEGIN TRY
            SET @sql = 'ALTER TABLE ' +@schema+'.'+ @table + ' ALTER COLUMN ' + @column_name + ' ' + @data_type + '(' + CAST(@max_length AS nvarchar(100)) + ') COLLATE ' + @collate
            print @sql
            EXEC sp_executesql @sql
        END TRY
        BEGIN CATCH
          PRINT 'ERROR:'
          PRINT @sql
        END CATCH

        FETCH NEXT FROM tbl_cursor_changed
        INTO @row_id, @column_name, @data_type, @max_length, @column_id

    END

    CLOSE tbl_cursor_changed
    DEALLOCATE tbl_cursor_changed

    FETCH NEXT FROM tbl_cursor
    INTO @schema, @table

END

CLOSE tbl_cursor
DEALLOCATE tbl_cursor

PRINT 'Collation For All Tables Done!'
END

虽然它能处理模式,但要注意它不像其他一些工具那样处理NULL vs NOT NULL。 - Darren

1
我使用以下查询语句在表的每个字段上生成排序规则更新查询语句:
SELECT
    [query] = 
        'ALTER TABLE '+ c.TABLE_SCHEMA +
        '.[' + c.TABLE_NAME + 
        '] ALTER COLUMN [' + c.COLUMN_NAME + 
        '] nvarchar(' + IIF(c.CHARACTER_MAXIMUM_LENGTH = -1, 'MAX', CAST(c.CHARACTER_MAXIMUM_LENGTH AS NVARCHAR(50))) + 
        ') COLLATE Persian_100_CI_AI_SC_UTF8'
FROM INFORMATION_SCHEMA.COLUMNS AS c
LEFT JOIN sys.computed_columns  AS cc  ON cc.[name] = c.COLUMN_NAME
WHERE c.TABLE_CATALOG = 'Your_Table_Name' AND DATA_TYPE = 'nvarchar' AND cc.[object_id] IS NULL
    AND c.TABLE_NAME NOT IN ('sysdiagrams')
ORDER BY c.TABLE_NAME

在计算列上不起作用


0

这个答案可能有点晚了,但你也可以生成语句。这比使用CURSOR要快得多。

select 
'ALTER TABLE '+ tb.TABLE_NAME + ' ALTER COLUMN '+ cl.COLUMN_NAME + ' ' + DATA_TYPE +'('+ cast(CHARACTER_MAXIMUM_LENGTH as nchar(3)) + ') ' + 'COLLATE Latin1_General_CI_AS '
FROM [DATABASE].INFORMATION_SCHEMA.columns cl  
left join [DATABASE].tables tb on tb.TABLE_NAME = cl.TABLE_NAME and tb.Table_Schema=cl.table_schema 
left join  [DATABASE].INFORMATION_SCHEMA.KEY_COLUMN_USAGE kc on kc.table_name = tb.table_name and kc.TABLE_SCHEMA = cl.TABLE_SCHEMA  and kc.column_name=cl.COLUMN_NAME
WHERE DATA_TYPE in ('nvarchar','nchar')

希望这能帮助到某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接