查询失败"将字符串转换为smalldatetime数据类型"

时间:2016-04-27 22:03:33

标签: sql-server tsql predicate culture date-conversion

我的任务是修复一些不起作用的SQL代码。查询从谓词中读取谓词。现在的查询看起来就是这样。

SELECT  TOP (100) Beginn
FROM  V_LLAMA_Seminare
//Removal of the following line makes the query successful, keeping it breaks it
where Beginn  > (select cast (getdate() as smalldatetime))
order by Beginn desc

当我运行上述查询时,我遇到以下错误。

Msg 295, Level 16, State 3, Line 1
Conversion failed when converting character string to smalldatetime data type.

我决定删除WHERE子句,现在它运行返回100行。

起初,我认为在幕后,SQL Server在恢复View时会以某种方式包含我的谓词。但后来我研究了如何创建View,特别是Beginn字段,并且它没有返回String。

长话短说,成为Beginn字段的列是一个BIGINT时间戳,如201604201369 ....原始用户使用以下魔法将此BIGINT转换为smalldatetime。

....
CASE WHEN ma.datum_dt = 0 
   THEN null 
   ELSE CONVERT(smalldatetime, SUBSTRING(CAST(ma.datum_dt AS varchar(max)),0,5) + '-' + 
   SUBSTRING(CAST(ma.datum_dt AS varchar(max)),5,2)  + '-' + 
   SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) +  ' ' + 
   SUBSTRING(CAST(ma.datum_dt AS varchar(max)),9,2) +':'+
   SUBSTRING(CAST(ma.datum_dt AS varchar(max)),11,2) +':' + 
   RIGHT(CAST(ma.datum_dt AS varchar(max)),2)) END AS Beginn
...

我最后一次尝试找到问题的方法是查询视图并在Beginn列上运行ISDATE函数,看看它是否返回了0,它从未发生过。

所以我的问题是双重的,"为什么谓词会破坏某些东西"两个"这个字符串错误来自何时从BIGINT"形成Beginn值。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

这个问题与文化有关......

尝试此操作,然后将第一个SET LANGUAGE更改为GERMAN

SET LANGUAGE ENGLISH;
DECLARE @bi BIGINT=20160428001600;
SELECT CASE WHEN @bi = 0 
   THEN null 
   ELSE CONVERT(datetime, SUBSTRING(CAST(@bi AS varchar(max)),0,5) + '-' + 
   SUBSTRING(CAST(@bi AS varchar(max)),5,2)  + '-' + 
   SUBSTRING(CAST(@bi AS varchar(max)),7,2) +  ' ' + 
   SUBSTRING(CAST(@bi AS varchar(max)),9,2) +':'+
   SUBSTRING(CAST(@bi AS varchar(max)),11,2) +':' + 
   RIGHT(CAST(@bi AS varchar(max)),2)) END AS Beginn

这是一个非常糟糕的习惯,认为日期值在任何地方看起来都一样(哦不,我的小应用程序永远不会走向国际 ...)

尝试坚持使用ODBC or ISO

等与文化无关的格式

修改

一个非常简单的解决方案实际上是用“T”替换空白

   SUBSTRING(CAST(ma.datum_dt AS varchar(max)),7,2) +  'T' + 

然后它是ISO 8601并将转换...

答案 1 :(得分:0)

在查看@ Shnugo的评论之后找到了解决方案。当我接受包含Bigint->日期时间转换逻辑的查询时,将其放入带有" TOP 100000000"的CTE中。为了避免任何隐式转换操作,我的查询工作。以下是我的视图现在的情况,省略了一些不重要的部分。

---Important part---
CREATE VIEW [dbo].[V_SomeView] AS
WITH CTE AS (
SELECT TOP 1000000000 ma.id AS MA_ID,
---Important part---
   vko.extkey AS ID_VKO,
   vko.text AS Verkaufsorganisation,
   fi.f7000 AS MDM_Nr,
   vf.f7105 AS SAPKdnr,
   CASE WHEN ma.datum_dt = 0 --Conversion logic
   CASE WHEN ma.endedatum_dt = 0 --Conversion logic
   CONVERT(NVARCHAR(MAX),art.text) AS Art,
    .....
FROM [ucrm].[dbo].[CRM_MA] ma,
[ucrm].[dbo].[CRM_fi] fi,
[ucrm].[dbo].[CRM_vf] vf,
[ucrm].[dbo].[CRM_ka] vko,
[ucrm].[dbo].[CRM_ka] art,
[ucrm].[dbo].[CRM_ka] kat
where ma.loskz = 0
and fi.loskz = 0
and vf.loskz = 0
and fi.F7029 = 0
and vf.F7023 = 0
...
GROUP BY ma.id,
   vko.extkey,
   vko.text,
   fi.f7000 ,
   vf.f7105,
   ma.datum_dt,
   ma.endedatum_dt,
   ....
)
select * FROM CTE;