【问题标题】:SQL Server: How to change collation of all columns of my select on the flySQL Server:如何即时更改我选择的所有列的排序规则
【发布时间】:2019-05-12 09:26:06
【问题描述】:

我需要从数据库中的表中查询某些内容,但某些列的排序规则与我需要的不同。

我发现如何像这样动态更改一列的排序规则:

SELECT 
  u.name  COLLATE Latin1_General_CI_AS AS 'User'(...)

但问题是有超过 150 列需要即时更改 COLLATION(不要问我为什么,因为我们无法更改整个表的排序规则,即使我认为这将是最佳选择)。

所以主要问题是: Is there a way to set the COLLATION to all columns of my query?

【问题讨论】:

  • 将列列表复制到 Excel 中,制作生成排序规则表达式的公式,然后粘贴回 SQL 窗口。
  • 您是否有权在您的服务器实例上执行动态 SQL?
  • 您似乎还有另一个未解释的问题。例如,您是否需要这样做才能加入临时表(使用不同的排序规则)
  • 同意尼克 - 很可能是xy problem

标签: sql sql-server collation


【解决方案1】:

无法即时更改所有文本列的排序规则,但可以通过操作查询来获得相同的结果。 Martin's answer 展示了一种方法,这是另一种使用查询元数据的方法。作为一个好处,它是无游标的,如果排序规则已经是我们想要的,它可以避免无缘无故地引入“新”列。它至少要求 SQL Server 2012 有sys.dm_exec_describe_first_result_set,SQL Server 2017 有STRING_AGG(在以前的版本中,可以使用经典的字符串连接技巧,如FOR XML PATH 技巧)。

DECLARE @query NVARCHAR(MAX) = N'SELECT * FROM MyTable';
DECLARE @tweakedQuery NVARCHAR(MAX);
DECLARE @tweakedCollation SYSNAME = N'Latin1_General_CI_AS';

SELECT @tweakedQuery = CONCAT(
    'SELECT ', 
    STRING_AGG(
        CONCAT(
            CONVERT(NVARCHAR(MAX), QUOTENAME([name])), 
            CASE 
                WHEN collation_name IS NOT NULL AND collation_name <> @tweakedCollation
                THEN ' COLLATE ' + @tweakedCollation + ' AS ' + QUOTENAME([name]) 
            END
        ), 
        ', ' + CHAR(13) + CHAR(10)
    ),
    ' FROM (' + CHAR(13) + CHAR(10),
    @query,
    CHAR(13) + CHAR(10) + ') _'
)
FROM sys.dm_exec_describe_first_result_set(@query, NULL, NULL);
PRINT @tweakedQuery;

如果系统地生成自定义别名(基于表或列名),则合并自定义别名会很简单。否则你将不得不手动修补。

对于一次性查询(不是您必须即时执行的操作),熟悉在您最喜欢的编辑器中使用正则表达式仍然是一个更好的主意。如果你最喜欢的编辑器没有正则表达式,那就买一个吧。

【讨论】:

    【解决方案2】:

    我不确定是否有办法以这种方式对输出的所有列强制使用默认排序规则。

    但是,如果您的服务器允许您使用动态 SQL,您可以构建一个动态查询并执行它以获得您正在寻找的结果。

    这个工作的一个例子如下所示。请将YOUR_TABLE_NAME 更改为您的实际表名以使其正常工作:

    DECLARE @col    VARCHAR(200)
    DECLARE @sql    VARCHAR(MAX)
    DECLARE @table  VARCHAR(200)
    SET @table = 'YOUR_TABLE_NAME';
    
    -- Use a cursor to read all varchar columns from table
    DECLARE curColumns CURSOR FORWARD_ONLY STATIC READ_ONLY
      FOR
        SELECT  c.name
          FROM  sys.columns c
            INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
          WHERE c.object_id = OBJECT_ID(@table) AND
                t.name = 'varchar'
    
    SET @sql = 'SELECT'
    
    -- Go through column cursor
    OPEN curColumns
    FETCH NEXT FROM curColumns INTO @col
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        -- Add column to SQL with collation
        SET @sql = @sql + ' ' + @col + ' COLLATE Latin1_General_CI_AS,'
    
        FETCH NEXT FROM curColumns INTO @col
    END
    CLOSE curColumns
    DEALLOCATE curColumns
    
    -- Add the from clause
    SET @sql = SUBSTRING(@sql, 0, LEN(@sql) - 1) + ' FROM ' + @table
    
    -- Uncomment this line to see the generated SQL
    --PRINT @sql
    EXEC (@sql)
    

    请注意,上述示例有几个限制:

    1. 您的服务器必须允许运行动态 SQL。
    2. 在此示例中,仅输出 VARCHAR 列(您可以通过更改游标查询以包含更多类型来更改此设置)。
    3. 无法使用此方法指定列别名。

    【讨论】:

      猜你喜欢
      • 2013-08-09
      • 2020-12-16
      • 2011-03-28
      • 2016-11-17
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 2015-04-03
      相关资源
      最近更新 更多