2013-06-11 13 views
5

Ich versuche, einen NULL-Wert an einen TSQLDataset-Parameter übergeben. Die Abfrage hat das folgende Format:Übergabe von NULL-Wert in parametrisierten Delphi-SQL-Server-Abfrage

Query_text:='MERGE INTO [Table] 
      USING (VALUES (:A,:B)) AS Source (Source_A, Source_B) 
      .... 
      WHEN MATCHED THEN 
      UPDATE SET A = :A 
      WHEN NOT MATCHED THEN 
      INSERT(A, B) VALUES (:A,:B); 

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text; 

SQL_dataset.ParamByName('A').AsString:='A'; 
SQL_dataset.ParamByName('B').AsString:={ COULD BE NULL, OR A STRING };  

SQL_dataset.ExecSQL; 

Parameter B ist nullfähig, ist aber auch ein Fremdschlüssel. Wenn der Benutzer etwas in dieses Feld eingibt, muss B mit Werten in einer anderen Tabelle verglichen werden. Wenn es leer ist, möchte ich, dass es ignoriert wird. Ich bin reingegangen, aber das erzeugt offensichtlich einen FK-Verletzungsfehler.

Ich habe versucht:

SQL_dataset.ParamByName('B').Value:=Null; 

..aber dann bekomme ich eine Fehlermeldung „dbexpress Treiber den tdbxtypes.unknown Datentyp nicht unterstützt“.

ich auch versucht:

SQL_dataset.ParamByName('B').DataType:=ftVariant; 
SQL_dataset.ParamByName('B').Value:=Null; 

..aber dann bekam "dbexpress Treiber unterstützt nicht die tdbxtypes.variant Datentyp" Fehler.

Nicht sicher, was ich falsch mache, würde jede Hilfe geschätzt werden. Ich erstelle derzeit eine Parameterliste, basierend darauf, ob die Zeichenfolge ausgefüllt ist oder nicht, und das funktioniert gut; es ist nur ein bisschen klobig (in meiner eigentlichen Abfrage), da es einige Parameter zu validieren gibt.

Ich verwende Delphi XE4 und SQL Server 2012.

Update:

Vielen Dank für all die Hilfe, Anregungen entlang Recht vor, alle waren, war es etwas anderes, das das 'dbexpress Fahrer produziert Error. Ich war eine ‚flexible‘ Parameterliste in dem Bemühen, zu schaffen um mein Problem zu bekommen, und dies die Ausnahme verursacht:

Parameter_string:=''; 

If B<>'' then Parameter_string:='B = :B,' 

Query_text:='MERGE ...' 
      '...' 
      'UPDATE SET A = :A, '+Parameter_string+' C = :C' .... 

... die Idee ist, dass wenn B leer ist, dann wird der Parameter nicht " in der Abfrage aufgelistet.

Das funktioniert nicht, oder meine Implementierung funktioniert nicht (nicht sicher warum, ich vermisse offensichtlich einen Schritt irgendwo).

Wie dem auch sei, die Arbeitscode:

Query_text:='MERGE ...' 
      '...' 
      'UPDATE SET A = :A, B = :B, C = :C' .... 

SQL_dataset.CommandType:=ctQuery; 
SQL_dataset.CommandText:=Query_text; 

If B<>'' then 
begin 
    SQL_dataset.ParamByName('B').AsString:='B'; 
end 
else 
begin 
    SQL_dataset.ParamByName('B').DataType:=ftString; 
    SQL_dataset.ParamByName('B').Value:=Null; 
end; 

Antwort

1

Wenn ich mich richtig erinnere, die db-Null-Äquivalent in Delphi ist Variants.Null

0

Übliche Ansatz würde Parameter einmal pro Abfrage verwenden und weisen Sie den entsprechenden Datentyp. Wert kann NULL zugewiesen werden.

var 
Query_text:String; 
begin 
    Query_text:='Declare @A varchar(100) ' // or e.g. integer 
     +#13#10'Declare @B varchar(100)' 
     +#13#10'Select @A=:A' 
     +#13#10'Select @B=:B' 
     +#13#10'Update Adressen Set [email protected],[email protected] where [email protected]'; 
    SQL_dataset.CommandType := ctQuery; 
    SQL_dataset.CommandText := Query_text; 
    SQL_dataset.Params.ParseSQL(SQL_dataset.CommandText,true); 
    Showmessage(IntToStr(SQL_dataset.Params.Count)); 
    SQL_dataset.ParamByName('B').DataType := ftString; 
    SQL_dataset.ParamByName('B').Value := 'MyText'; 
    SQL_dataset.ParamByName('A').DataType := ftString; // or e.g. ftInteger 
    SQL_dataset.ParamByName('A').Value := NULL; 
    SQL_dataset.ExecSQL; 
end; 
+0

Danke, ich dies versuchte, gleiche Fehler wie oben in Kommentar zu @ pf1957 zur Kenntnis genommen. Mayve Ich habe etwas anderes, das diesen Fehler einschließt? – Alex

+0

Danke für die Hilfe, siehe Update. – Alex

2

was:

SQL_dataset.ParamByName('B').Clear;

+0

Ich hatte diesen Vorschlag an anderer Stelle gelesen, aber ich bekomme den "dbExpress-Treiber unterstützt den TDBXTypes.UNKNOWN-Datentyp nicht. Hersteller Fehlermeldung:" Fehler, wenn ich das versuche. Mache ich etwas anderes falsch? – Alex

+0

Seltsam ...Zur Zeit migriere ich von FIB + zu FireDAC und habe es auf beiden Verbindungen getestet und es ist möglich entweder Clear oder Value: = null zu verwenden. Und ich würde erwarten, dass es für jeden Datensatz funktioniert. Zumindest habe ich noch nie ein Problem damit gehabt, aber ich habe nie dbExpress benutzt. – pf1957

+0

Danke nochmal, du hast recht, siehe update oben. – Alex