La requête échoue lors de la "conversion de la string de caractères en type de données smalldatetime"

J'ai été chargé de réparer du code SQL qui ne fonctionne pas. La requête lit à partir d'une vue par rapport à un prédicat. La requête en ce moment ressemble à cela.

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 

Lorsque j'exécute la requête ci-dessus, je suis accueilli avec l'erreur suivante.

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

J'ai décidé de supprimer la clause WHERE, et maintenant il fonctionne en renvoyant 100 lignes.

Au début, je pensais que dans les coulisses, SQL Server incluait en quelque sorte mon prédicat lors du return de la vue. Mais j'ai ensuite étudié comment la vue était créée, en particulier le champ Beginn, et à aucun moment elle ne renvoie une string.

Longue histoire courte, la colonne qui devient le champ Beginn est un horodatage BIGINT comme 201604201369 …. L'user original transforme ce BIGINT en un petit time en utilisant la magie suivante.

 .... 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 ... 

Ma dernière tentative pour find le problème était d'interroger la vue et d'exécuter la fonction ISDATE sur la colonne Commencer et voir si elle renvoyait un 0 qu'elle n'a jamais fait.

Donc ma question est double: "Pourquoi un prédicat brise-t-il quelque chose" et deux "Où est-ce que cette erreur de string vient de quand la valeur de Beginn est formée à partir d'un BIGINT".

Toute aide est grandement appréciée.

Ce problème est lié à la culture …

Essayez ceci et changez le premier SET LANGUAGE en 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 

C'est une très mauvaise habitude de penser, que les valeurs de date se ressemblent partout ( Oh non, ma petite application ne sera jamais internationale …)

Essayez de coller à des formats indépendants de la culture comme ODBC ou ISO

MODIFIER

Une solution très simple pour vous était de replace le blanc par un "T"

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

Ensuite, c'est ISO 8601 et va convertir …

La solution a été trouvée après avoir regardé le commentaire de @ Shnugo. Quand j'ai pris ma requête qui contenait la logique de conversion Bigint-> Datetime, et l'ai mise dans un CTE avec "TOP 100000000" pour éviter toute action de conversion implicite, ma requête a fonctionné. Voici à quoi ressemble ma vue maintenant avec des parties sans importance omises.

 ---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;