如何在T-SQL表值函数内切换语言

4

我需要在表值函数的主体内切换语言,以返回不同语言的月份名称和工作日。但是,当我尝试使用SET LANGUAGE RUSSIAN时,我会收到Invalid use of a side-effecting operator 'SET COMMAND' within a function.错误。

为什么在TVF中设置变量可以正常运行,而更改语言却会出错?我该如何在TVF中更改语言?

2个回答

4

您不能在函数内使用 set language

您使用的是哪个版本?

如果是2012年及以后的版本,您可以执行以下操作:

SELECT FORMAT (GETDATE(), 'dddd', 'ru-RU'), 
       FORMAT (GETDATE(), 'MMMM', 'ru-RU')

在新版本中,你可以使用内置的函数替代。 (在回答的那天返回 вторник, Сентябрь)。

在之前的版本中,你可以编写类似的CLR函数。


太好了,Martin!非常感谢!这对我来说非常完美。顺便说一下,我在使用2014年的版本。 - erop

3

在2012版本之前,您可以使用sys.syslanguages表来提取月份名称,例如:

CREATE VIEW dbo.MonthNameByLanguage
AS
    WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
    Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N1 AS N1 CROSS JOIN N1 AS N2)
    SELECT  l.langid,
            languageName = l.name,
            l.alias,
            MonthNumber = ROW_NUMBER() OVER(PARTITION BY l.[langid] ORDER BY n.Number),
            [MonthName] = SUBSTRING(l.months, n.Number, CHARINDEX(',', l.months + ',', n.Number) - n.Number)
    FROM    sys.syslanguages AS l
            INNER JOIN Numbers AS n
                ON (SUBSTRING(l.months, n.Number -1, 1) = ',' OR n.Number = 1);

这仅仅是从系统视图获取逗号分隔的月份名称,并使用一个数字表进行拆分。然后您可以将其用作函数内部的:

SELECT  MonthName
FROM    dbo.MonthNameByLanguage
WHERE   alias = 'RUSSIAN'
AND     MonthNumber = 3;

一般来说,我建议您尽可能晚地进行格式化。只需将日期传递给演示层,让区域设置处理格式即可。

对于星期几,您也可以采取类似的做法:

CREATE VIEW dbo.DayNameByLanguage
AS
    WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
    Numbers (Number) AS (SELECT ROW_NUMBER() OVER(ORDER BY N1.N) FROM N1 AS N1 CROSS JOIN N1 AS N2)
    SELECT  l.langid,
            languageName = l.name,
            l.alias,
            DayNumber = ROW_NUMBER() OVER(PARTITION BY l.[langid] ORDER BY n.Number),
            [DayName] = SUBSTRING(l.days, n.Number, CHARINDEX(',', l.days + ',', n.Number) - n.Number)
    FROM    sys.syslanguages AS l
            INNER JOIN Numbers AS n
                ON (SUBSTRING(l.days, n.Number -1, 1) = ',' OR n.Number = 1);

谢谢你的回答,Gareth!看起来2012年以后的版本在减少代码量方面取得了巨大进展。 - erop
完全没有问题。我会把我的技巧描述为最好的黑客技巧,它使用了 SQL Server 中的系统表,可能不是它们的本意。但是,是的,2012 年以后引入的 FORMAT() 在这种情况下使您的生活变得更加轻松! - GarethD

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