sql
  • sql-server
  • xml
  • null
  • decimal
  • 2016-08-17 9 views 1 likes 
    1

    Wie füge ich einfach NULL ein, wenn der Knoten leer oder nicht vorhanden ist?Empty XML-Knoten verursacht Fehler beim Konvertieren des Datentyps varchar in numerisch

    CREATE TABLE myxml (
        "hours" DECIMAL(11,2) 
    ); 
    
    DECLARE @xml XML = 
    '<?xml version="1.0" encoding="UTF-8"?> 
    <Data> 
        <Employee> 
         <NUMHOURS>0.5</NUMHOURS> 
        </Employee> 
        <Employee/> 
        <Employee> 
         <NUMHOURS>5</NUMHOURS> 
        </Employee> 
        <Employee> 
         <NUMHOURS/> 
        </Employee> 
    </Data>'; 
    
    INSERT INTO myxml ("hours") 
    SELECT 
        t.c.value('NUMHOURS[1]','DECIMAL(11,2)') 
    FROM @xml.nodes('/Data/Employee') t(c) 
    

    Der leere Knoten <NUMHOURS/> verursacht:

    Fehlerdatentyp nvarchar in numerische Umwandlung.

    Ich habe versucht:

    NULLIF(t.c.value('NUMHOURS[1]','DECIMAL(11,2)'),'') 
    

    aber das scheint nach der Tat verarbeitet werden im gleichen Fehler führt.

    +0

    Ein leerer Knoten wird von SQL Server nicht als null betrachtet, es gilt als eine leere [b] Zeichenfolge [/ b]. Im Gegensatz dazu wird die Abwesenheit eines Knotens als null betrachtet. In Ihrem Fall sollten Sie 'CAST (NULLIF (t.cvalue ('NUMHOURS [1]', 'varchar (13)'), '') AS DECIMAL (11,2))' verwenden. Sie könnten 'varchar (13)' in etwas Größeres ändern, um für ungültige Werte (die nicht 'dezimal (11,2)' passen) –

    +0

    oder Sie können versuchen, SELECT tcvalue ('(./ text()) [ 1] ',' DECIMAL (11,2) ') FROM @ xml.nodes ('/Daten/Mitarbeiter/NUMHOURS ') t (c) ' – JamieD77

    Antwort

    2

    Sie können einen Standardwert für ungültige Nummern bieten:

    select case 
          when ISNUMERIC(t.c.value('NUMHOURS[1]', 'nvarchar(100)')) <> 1 then NULL 
          else t.c.value('NUMHOURS[1]', 'decimal(11,2)') 
         end 
        from @xml.nodes('/Data/Employee') t(c) 
    
    +0

    Die Frage war, wie man' NULL 'einfügt, also habe ich Ihre Antwort passend bearbeitet . Vielen Dank! –

    +0

    Die Frage war, wie NULL für leere oder fehlende Knoten eingefügt werden, nicht für ungültige Werte. IMHO ungültige Werte sollten fehlschlagen, oder noch besser, die XML sollte gegen eine DTD oder XSD validiert werden, bevor sie an SQL Server übergeben wird. –

    +0

    Ich mag diese direkte Annäherung, +1 von meiner Seite. Sie könnten an einer anderen Lösung interessiert sein, bei der die Besetzung intern erfolgt. Ich finde das sehr hilfreich, wenn ich mich mit XML typsicher beschäftige ... – Shnugo

    1

    Es könnte einen besseren Ansatz sein: (sollte zumindest schneller mit vielen Reihen sein ...):

    SELECT t.c.value('let $x:=NUMHOURS[1] return $x cast as xs:decimal?','decimal(11,2)') 
    FROM @xml.nodes('/Data/Employee') t(c); 
    

    Die cast as xs:decimal? wird den Wert wenn möglich in Dezimalzahlen umwandeln oder null zurückgeben. So hat die endgültige 'decimal(11,2)' keine Art Konvertierungsproblem mehr ...

    Verwandte Themen