【问题标题】:use set language in a sql function在 sql 函数中使用设置语言
【发布时间】:2015-09-08 22:25:38
【问题描述】:

我想在函数中使用DATENAME,但问题是日期名称的结果取决于登录或安装语言设置。

为了确保它始终返回英文结果,我需要使用set language 'English',但如果我在函数中使用它,我会收到以下错误

在函数中无效使用副作用运算符“SET COMMAND”。

【问题讨论】:

  • 你不能。目前尚不清楚您要实现什么,但我可以看到使用DATENAME 的主要原因是提供一些日期格式,这是表示层而不是 SQL 的工作。如果我弄错了,并且确实需要知道英文日期名称,那么您最好的选择是创建一个calendar table,并为每个日期添加带有英文日期名称的列,然后在您的函数中使用它。

标签: sql-server tsql sql-server-2008 user-defined-functions date-formatting


【解决方案1】:

对于使用 SQL Server 2012 或更高版本的任何人,通过 FORMAT 函数很容易做到这一点,如下所示:

SET LANGUAGE 'English';

DECLARE @TestDate DATETIME;
SET @TestDate = '2015-06-23';

SELECT FORMAT(@TestDate, 'dddd'); -- Tuesday
SELECT FORMAT(@TestDate, 'dddd', 'en-us'); -- Tuesday
SELECT FORMAT(@TestDate, 'dddd', 'ru-RU'); -- вторник
SELECT FORMAT(@TestDate, 'dddd', 'fa-IR'); -- سه شنبه

SET LANGUAGE 'French';

SELECT FORMAT(@TestDate, 'dddd'); -- mardi
SELECT FORMAT(@TestDate, 'dddd', 'en-us'); -- Tuesday
SELECT FORMAT(@TestDate, 'dddd', 'ru-RU'); -- вторник
SELECT FORMAT(@TestDate, 'dddd', 'fa-IR'); -- سه شنبه

但是仍然使用 SQL Server 2005、2008 或 2008 R2 的人呢?好吧,同样可以使用 SQLCLR 完成。事实上,SQL Server 2012 中引入的FORMAT 函数(即上面显示的函数)在幕后使用了 SQLCLR。因此,您可以编写一个简单的 CLR UDF 来执行此操作,或者您可以简单地下载 SQL# 库(我是该库的作者,但此函数在免费版本中可用)并使用 Date_Format 函数,如此处显示:

SET LANGUAGE 'English';

DECLARE @TestDate DATETIME;
SET @TestDate = '2015-06-23';

SELECT SQL#.Date_Format(@TestDate, 'dddd', ''); -- Tuesday
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'en-us'); -- Tuesday
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'ru-RU'); -- вторник
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'fa-IR'); -- سه شنبه

SET LANGUAGE 'French';

SELECT SQL#.Date_Format(@TestDate, 'dddd', ''); -- Tuesday (Windows lang, not SQL Server's)
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'en-us'); -- Tuesday
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'ru-RU'); -- вторник
SELECT SQL#.Date_Format(@TestDate, 'dddd', 'fa-IR'); -- سه شنبه

SQL# Date_Format 函数与内置 FORMAT 函数具有基本相同的签名,除了第三个参数(文化)不能在 SQLCLR 函数中省略,因此当不使用文化时,它需要设置为空字符串''。另一个区别是 SQLCLR 似乎不知道当前会话 LANGUAGE 设置,因此默认区域性是 Windows 设置的任何内容(但在这种特殊情况下这不是问题)。

附:有关更多格式选项,请参阅 Custom Date and Time Format Strings 的 MSDN 页面。

【讨论】:

  • 此选项仅支持 SQL 2012 及更高版本但此问题发布在 SQL 2008 下。
  • @AnandaKumarJayaraman 是的,问题是关于 SQL Server 2008,我专门解决了这个问题,甚至给出了一个适用于 SQL Server 2005、2008 和 2008 R2 的示例。为了完整起见,我添加了有关 FORMAT 函数的信息。
【解决方案2】:

你可以试试这个吗?

select  
  case datepart(dw,getdate())
  when  isnull(nullif((7- @@datefirst + 1) % 7,0),7)  then 'Sunday'
  when  isnull(nullif((7- @@datefirst + 2) % 7,0),7) then 'Monday'
  when  isnull(nullif((7- @@datefirst + 3) % 7,0),7) then 'Tuesday'
  when  isnull(nullif((7- @@datefirst + 4) % 7,0),7) then 'Wednesday'
  when  isnull(nullif((7- @@datefirst + 5) % 7,0),7) then 'Thursday'
  when  isnull(nullif((7- @@datefirst + 6) % 7,0),7) then 'Friday'
  when  isnull(nullif((7- @@datefirst + 7) % 7,0),7) then 'Saturday'
end;

【讨论】:

  • 这遇到了 OP 已经尝试解决的完全相同的问题:基于语言的设置。 @@DATEFIRST 值基于当前语言,因此会随着不同的SET LANGUAGE 值而变化,就像DATENAME 输出一样。有关示例,请参阅 @@DATEFIRST 的 MSDN 页面。
  • 在发表任何评论之前,请先尝试再发表评论。完整阅读代码,然后写下您的评论。
  • 我测试过,但不是整个查询包括DATEPART() 函数,我忘记了也对@@DATEFIRST 的值敏感。所以是的,这似乎确实有效。对不起,我的测试没有更彻底。我试图删除反对票,但它给了我一个错误,说除非编辑答案,否则它已被锁定。因此,如果您进行了较小的修改,我应该能够删除反对票。
  • 由于某种原因您的编辑没有注册,所以我做了一个小的代码格式更改,然后能够将反对票更改为赞成票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-27
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 2021-01-31
  • 1970-01-01
相关资源
最近更新 更多