转换 DATETIME 时是否可以更改 CAST/CONVERT 使用的默认样式?

oco*_*erj 5 sql-server cast datetime

当您尝试在 SQL Server 中将 DATETIME 转换为 VARCHAR 时,默认的日期格式样式是一种相当不准确的日期格式,会丢失秒和毫秒的精度。例如:

SELECT CAST(GETDATE() AS VARCHAR)
-- May  8 2015  9:13AM
Run Code Online (Sandbox Code Playgroud)

有没有办法更改使用的默认样式?例如,我想使用样式 126 使结果看起来更像这样:

SELECT CAST(GETDATE() AS VARCHAR)
-- 2015-05-08T09:14:19.437
Run Code Online (Sandbox Code Playgroud)

如果可能,我只想更改当前流程或语句的默认样式;但是,我也愿意在数据库或模式级别更改它。

我应该注意:我知道 CONVERT 和手动指定样式的能力。但是,在这种特殊情况下,我无法使用 CONVERT。我将 SQL_VARIANT 参数作为 VARCHAR 转换为标量值函数。

Aar*_*and 7

CAST根本不支持除通用转换之外的任何其他功能,除了固有的灵活性之外没有任何灵活性(例如语言或日期格式设置,这与日期字符串的解释方式有关,而不是它具有多少精度)。无论使用何种方法,日期时间 -> 字符串的通用转换都会失去精度。这些都没有秒:

PRINT GETDATE();
SELECT CAST(GETDATE() AS VARCHAR(23));
SELECT CONVERT(VARCHAR(23), GETDATE());
Run Code Online (Sandbox Code Playgroud)

答案是使用CONVERT 适当的长度和样式编号(并且没有理由单独使用VARCHAR此转换)。

SELECT CONVERT(CHAR(23), GETDATE(), 126);
Run Code Online (Sandbox Code Playgroud)

抱歉,没有服务器级、数据库级或架构级设置可以自动执行此操作(或更改CAST工作方式)。

关于您认为存在的特定问题(CONVERT由于SQL_VARIANT参数错误而无法使用),您可以DATETIMECASE表达式中强制转换为as以避免在直接转换不可转换值时出错。这些形式中的任何一种都可以使用:

DECLARE @x TABLE(y SQL_VARIANT);
INSERT @x(y) VALUES(GETDATE());
INSERT @x(y) VALUES('foo');

SELECT CASE WHEN ISDATE(CONVERT(CHAR(23), y)) = 1 
  THEN CONVERT(CHAR(23), CONVERT(DATETIME, y), 126) 
  ELSE y END
  FROM @x;

SELECT CONVERT(VARCHAR(4000), 
  CASE WHEN ISDATE(CONVERT(CHAR(23), y)) = 1 
  THEN CONVERT(DATETIME, y) ELSE y END, 126)
  FROM @x;
Run Code Online (Sandbox Code Playgroud)

在您说这一定是低效之前,您正在使用SQL_VARIANT标量用户定义函数。这些额外的单例值转换将只是杯水车薪。

免责声明:使用这种方法您仍然可能会遇到错误,因为ISDATE()测试只检查可能是与垃圾连接的有效日期时间字符串的前 23 个字符。例如:

INSERT @x(y) VALUES('2000-01-01T00:00:00.000 garbage');
Run Code Online (Sandbox Code Playgroud)

使用与上面相同的代码将导致:

消息 241,级别 16,状态 1
从字符串转换日期和/或时间时转换失败。

因此,下面 Paul 建议使用稍微安全一些的方法,使用SQL_VARIANT存储的元数据来确保您只尝试转换具有日期/时间基类型的数据。这也允许您忽略字符串长度等(输出除外)。

DECLARE @x TABLE(y SQL_VARIANT);
INSERT @x(y) VALUES(GETDATE());
INSERT @x(y) VALUES('foo');
INSERT @x(y) VALUES('2000-01-01T00:00:00.000 garbage');

SELECT CASE 
  WHEN CONVERT(SYSNAME, SQL_VARIANT_PROPERTY(y, 'BaseType')) LIKE N'%date%' 
  THEN CONVERT(CHAR(23), CONVERT(DATETIME, y), 126) 
  ELSE y END
  FROM @x;
Run Code Online (Sandbox Code Playgroud)

在未来,而不只是含糊地说:“我无法用CONVERT”,告诉我们你是什么真正做的,为什么你居然认为你不能做一些事情。这里有些非常聪明的人可以理解和分析,而无需拔牙或做出假设。