0
votes

Impossible de convertir VarcharN en DateTime - Échec de la conversion lors de la conversion de la date et / ou de l'heure de la chaîne de caractères

Les données sources avec lesquelles je travaille, c'est tout dans une colonne appelée corps. Ces données ne peuvent malheureusement pas être modifiées. Les données arrivent via un email de l'extérieur de notre réseau, il entre alors dans Email2DB. E-mail2db est une application qui place les données de messagerie dans une table.

Ce n'est pas la manière dont les données sont généralement stockées dans nos tables, il s'agit d'une chose temporaire en place pour enregistrer des problèmes de PC de l'utilisateur, tout en éteignant le nombre de problèmes. peut être suivi. p>

corps p> xxx pré>

à des fins de reporting, je divise les données dans des colonnes individuelles. P>

J'ai besoin d'obtenir la date et l'heure distinctes pour être dans une colonne en tant que format DateTime. Par exemple: 2020-05-21 16:01 code> p>

J'essaie d'entrer les données dans la table TEMP suivante, mais pour la vie de moi, je ne peux pas obtenir la date et Il est temps de convertir en DateTime. p> xxx pré>

si je modifie la table TICKEDATEDATEDATEDER pour être TICKEDATE VARCHAR (25) Les données vont bien. Cependant, l'objectif final est de pouvoir passer dans un @Datefrom et @Dateto et être capable de faire un service de billetterie entre @Datefrom et @dateto et je ne peux pas faire cela à moins que TICKEDATED est format DateTime. P>

Qu'est-ce que je Je ne peux pas comprendre, c'est même si j'insère les données dans une table TEMP avec le ticket de Varchar, le résultat ressemble au dessous p>

Résultat Si vous insérez TICKEDATED comme Varchar P>

one Les données sont dans la table temporaire que j'ai essayée d'exécuter une instruction SELECT à l'aide de DateTime et de distribution En tant que DateTime2 et a également essayé de convertir en DateTime, mais rien ne fonctionne, je reçois toujours la même erreur p>

La conversion a échoué lors de la conversion de la date et / ou du temps de la chaîne de caractères. P> blockQuote>

J'ajouterai l'une des tentatives que j'ai essayé ci-dessous si quelqu'un peut omettre, je serai si reconnaissant. P>

S'il vous plaît savoir que j'ai des idées sans fin et essayé des multi-formats pour le Date heure. P>

USE [Central]
GO
/****** Object:  UserDefinedFunction [dbo].[f_SplitString]    Script Date: 26/06/2020 00:07:31 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
ALTER FUNCTION [dbo].[f_SplitString]
(
  @multiwordstring VARCHAR(255),
  @wordnumber      integer,
  @delimiter char(1)
)
returns VARCHAR(255)
AS
  BEGIN
      DECLARE @remainingstring VARCHAR(255)
      SET @remainingstring=@multiwordstring

      DECLARE @numberofwords NUMERIC
      SET @numberofwords=(LEN(@remainingstring) - LEN(REPLACE(@remainingstring, @delimiter, '')) + 1)

      DECLARE @word VARCHAR(50)
      DECLARE @parsedwords TABLE
      (
         line NUMERIC IDENTITY(1, 1),
         word VARCHAR(255)
      )

      WHILE @numberofwords > 1
        BEGIN
            SET @word=LEFT(@remainingstring, CHARINDEX(@delimiter, @remainingstring) - 1)

            INSERT INTO @parsedwords(word)
            SELECT @word

            SET @remainingstring= REPLACE(@remainingstring, @word + @delimiter, '')
            SET @numberofwords=(LEN(@remainingstring) - LEN(REPLACE(@remainingstring, @delimiter, '')) + 1)

            IF @numberofwords = 1
              BREAK

            ELSE
              CONTINUE
        END

      IF @numberofwords = 1
        SELECT @word = @remainingstring
      INSERT INTO @parsedwords(word)
      SELECT @word

      RETURN
        (SELECT RTrim(LTrim(word))
         FROM   @parsedwords
         WHERE  line = @wordnumber)

  END


5 commentaires

Donc, ce 21/05/2020 | 16: 01 | PATHE 2.0 Délai | Pathe | LRW10 | Terence est une colonne ? Je pense que vous devez repousser et obtenir des données dans votre base de données dans un format meilleur et plus normalisé. En ce moment, ce n'est pas une base de données, c'est un fichier texte.


Avez-vous réellement essayé de construire votre requête dans des blocs individuels pour voir où il échoue? Dans mes tests simples (je n'ai pas votre implémentation de f_splitstring fonction) ça fonctionne. Exécutez ceci: Sélectionnez Convert (date, dbo.f_splitstring (corps, 1, '|'), 105), converti (date, dbo.f_splitstring (corps, 1, '|'), 105), 23))) , Convertir (date, dbo.f_splitstring (corps, 1, '|'), 105), 23)) + dbo.f_splitstring (corps, 2, '|') . S'il échoue, continuez à supprimer des blocs de code de la fin jusqu'à ce que vous puissiez réellement le problème.


@Aaronbertrand Les données entrent via un email d'une source externe non dans notre réseau, il passe ensuite par courrier électronique2DB. Cette application le met dans la table mais ne peut pas la séparer en différentes colonnes, pourquoi je suis bloqué avec de telles données difficiles à utiliser.


Cette chose de 20 ans ne peut rien faire sauf décharge ensemble complet de données dans une seule colonne? Peut-être qu'il est temps d'examiner différents logiciels.


Sur la base du fait que vous avez des espaces dans votre chaîne de texte, je soupçonne que votre fonction String Split se coupe et que vous perdez ainsi un espace entre les composants de la date et l'heure, je vous ai donc demandé de décoller votre requête pour trouver le problème. .


4 Réponses :


1
votes

Une option est d'analyser la chaîne via XML (JSON est une autre option si 2016)

Exemple fort> p>

Declare @YourTable Table ([ID] varchar(50),[body] varchar(150))  Insert Into @YourTable Values 
 (1,'21/05/2020| 16:01| Pathe 2.0 Delay| Pathe| LRW10| terence')
 

Select A.ID
      ,DateCol  = try_convert(datetime,Pos1+' '+Pos2,103)
      ,Issue    = Pos3
      ,Category = Pos4
      ,PCName   = Pos5
      ,[User]   = Pos6
 From  @YourTable A
 Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                      ,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
                From  ( values (cast('<x>' + replace((Select replace([body],'|','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml))) as A(xDim)
             ) B


0 commentaires

1
votes

Une autre approche consiste à créer une fonction valorisée de table comme celle-ci, qui renvoie une chaîne fractionnée dans l'ordre: xxx

alors vous pouvez pivoter cela pour extraire des éléments spécifiques: < Pré> xxx


1 commentaires

Meilleure datetime avec la cordon Concat



0
votes

Solution

Vos chaînes de fonctions de fractionnement de la chaîne, vous perdez donc l'espace entre les composants de la date et de l'heure. P>

Changez votre code P>

SELECT CONVERT(date, dbo.f_SplitString(body,1,'|'), 105) FROM t_Quick
SELECT CONVERT(date, dbo.f_SplitString(body,1,'|'), 105), 23)) FROM t_Quick
SELECT CONVERT(date, dbo.f_SplitString(body,1,'|'), 105), 23))  + dbo.f_SplitString(body,2,'|') FROM t_Quick


0 commentaires

0
votes

Merci à tous pour vos suggestions. J'ai finalement compris le problème cependant. Lors de la conversion du temps, il y a un espace "non ordinaire", l'espace ne peut pas être retiré par la garniture et la solution utilisait donc la sous-chaîne et fonctionnait bien.

    DECLARE @QuickData TABLE (TicketDate datetime, Issue varchar(50), Category varchar(50), ComputerName varchar(30), UserName varchar(50));


    INSERT INTO @QuickData  
        SELECT convert(datetime, try_CONVERT(VARCHAR(25), (TRIM(CONVERT(VARCHAR(10), CONVERT(date, dbo.f_SplitString(body,1,'|'), 105), 23))  + ' ' + substring(dbo.f_SplitString(body,2,'|'),2,5) + ':00'),120)), 
    dbo.f_SplitString(body,3,'|') as 'Issue', dbo.f_SplitString(body,4,'|') as 'Category',
    dbo.f_SplitString(body,5,'|') as 'PCName', dbo.f_SplitString(body,6,'|') as 'User' FROM t_Quick;


    Select * from @QuickData
    where TicketDate between @dateFrom and @dateTo
    order by 1 desc;


0 commentaires