2013-06-11 18 views
5

Próbuję przekazać wartość pustą do parametru TSQLDataset. Zapytanie ma postać:Przekazywanie wartości NULL do sparametryzowanego zapytania SQL delphi serwera

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; 

Parametr B jest zerowalny, ale jest również kluczem obcym. Jeśli użytkownik wprowadzi coś w tym polu, to B musi zostać sprawdzone względem wartości z innej tabeli. Jeśli jest pusty, chcę go zignorować. Mijałem w "", ale to oczywiście powoduje błąd naruszenia FK.

Próbowałem:

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

..ale potem dostać „dbExpress sterownik nie obsługuje typ danych tdbxtypes.unknown” błąd.

Próbowałem również:

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

..ale potem dostał "dbExpress sterownik nie obsługuje typ danych tdbxtypes.variant" błąd.

Nie jestem pewien, co robię źle, każda pomoc będzie doceniona. Obecnie przygotowuję listę parametrów na podstawie tego, czy łańcuch jest wypełniany, czy nie, i to działa dobrze; jest to po prostu trochę niezgrabne (w moim prawdziwym zapytaniu), ponieważ istnieje kilka parametrów do sprawdzenia poprawności.

używam Delphi XE4 i serwera SQL 2012.

Aktualizacja:

Dzięki za wszelką pomoc, wasze sugestie były rację, to było coś innego, że produkowane dbexpress że „sterownik” błąd. I było stworzenie „elastyczne” listę parametrów, starając się ominąć mój problem, a to spowodowało wyjątek:

Parameter_string:=''; 

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

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

... pomysł jest, że jeśli B jest puste to parametr nie będzie " na liście "w zapytaniu.

To nie działa, albo moja implementacja tego nie działa (nie jestem pewien dlaczego, oczywiście brakuje czegoś gdzieś).

Zresztą kod roboczych:

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; 

Odpowiedz

1

Jeśli dobrze pamiętam, odpowiednik db null w Delphi jest Variants.Null

0

Usual podejście byłoby za pomocą parametrów raz na zapytania i przypisać odpowiednią typ danych. Wartość może być przypisana wartości NULL.

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

Dzięki, to próbowałem, uzyskać ten sam błąd, jak wspomniano powyżej w komentarzu do @ pf1957. Czy mam coś jeszcze, co jest przyczyną tego błędu? – Alex

+0

Dzięki za pomoc, zobacz aktualizację. – Alex

2

co:

SQL_dataset.ParamByName('B').Clear;

+0

Przeczytałem tę sugestię w innym miejscu, ale dostaję "sterownik dbExpress nie obsługuje typu danych TDBXTypes.UNKNOWN Komunikat o błędzie dostawcy:" błąd, gdy próbuję tego. Czy robię coś złego? – Alex

+0

Dziwne ...obecnie migruję z FIB + do FireDAC i przetestowałem go na obu połączeniach i można użyć funkcji Wyczyść lub Wartość: = null. I spodziewam się, że działa na każdym zestawie danych. Przynajmniej nigdy nie spotkałem się z tym problemem, ale nigdy nie korzystałem z dbExpress. – pf1957

+0

Dzięki jeszcze raz, masz rację, zobacz aktualizację powyżej. – Alex

Powiązane problemy