AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken TADOCommand mit Parametern - PK-Verletzung
Thema durchsuchen
Ansicht
Themen-Optionen

TADOCommand mit Parametern - PK-Verletzung

Ein Thema von hyype · begonnen am 12. Jun 2012 · letzter Beitrag vom 13. Jun 2012
Antwort Antwort
Seite 1 von 2  1 2      
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#1

TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 13:26
Datenbank: MSSQL2008R2 • Version: ? • Zugriff über: ADO
Hallo Community!

Ich habe ein TADOCommand und befülle CommandText mit einem sql-statement-string, der ungefähr so aussieht:

DECLARE @TRANSE CHAR(8) = 'Transe00';
BEGIN TRANSACTION @TRANSE;
IF NOT EXISTS(SELECT * FROM ST_VKL WHERE ID=:@ID)
INSERT INTO ST_VKL (ID,NAME) VALUES(:@ID,:@NAME)
ELSE
UPDATE ST_VKL SET NAME=:@NAME WHERE ID=:@ID;
IF @@ERROR = 0
COMMIT TRANSACTION @TRANSE
ELSE
ROLLBACK TRANSACTION @TRANSE;

Dabei ist schonmal zu sagen, dass mein string in diesem vereinfachten Beispiel genau _2_ Parameter enthält, @ID und @NAME.
Beim Zuweisen des commandtextes werden aber automatisch 5 erstellt, nämlich @ID, @ID, @NAME, @NAME, @ID,
was besonders sinnvoll ist, liefert doch die methode parambyname nur einen zurück...
Egal, ich habe sie allesamt mit den richtigen Werten befüllt.
Dazu ist zu sagen, dass ich sie nach der automatischen Erstellung nur noch mit Werten befülle,
also weder den Typ, noch die Größe festlege, da ich das ganz allgemein umgesetzt habe und ich im allgemeinen Fall den Datentyp nicht kenne,
dazu benutze ich den Datentyp Variant.

Nun zu meinem eigentlichen Problem:
Wie man dem statement entnehmen kann wird geguckt, ob ein Datensatz mit der ID schon da ist,
wenn nein wird ein insert gemacht, wenn ja ein update - wie kann es da sein, dass ich beim executen eine PK-Verletzung kriege?
Das ist doch eigentlich VÖLLIG UNMÖGLICH!?!

Bin mit meinem Latein am Ende, ka was delphi da macht, habe bisher immer ohne Parameter gearbeitet und den string einfach so zusammengebaut und da geht das.
Und wenn ich mein sql-statement ins ManagementStudio kopiere und statt der Parameter die Werte einfüge, funktioniert alles einwandfrei...
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 13:32
Warum verwendest du nicht das vorhandene MERGE Statement und versuchst es selber nachzubilden?
Markus Kinzler
  Mit Zitat antworten Zitat
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#3

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 14:04
ich habe das immer so gemacht, jedoch ohne parameter
es ist ja auch absolut richtig so!
ich würde gern eine erklärung haben, wieso ein sql-statement, welches von der sache her sauber ist und niemals zu einer pk-verletzung führen kann, beim executen des tadocommands mit parametern eine pk-verletzung verursacht, weil das verstehe ich nciht und das kostet mich jetzt extrem viel zeit...
  Mit Zitat antworten Zitat
ele

Registriert seit: 18. Feb 2009
129 Beiträge
 
Delphi 2010 Professional
 
#4

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 14:20
Das Problem kenne ich.
Man kann einen Parameter nicht auf diese Weise wiederverwenden.

Inzwischen verwende ich SQL Variabeln um das zu Umgehen. Alternativ kannst du dafür sorgen, dass die Parameter nur jeweils einmal vorkommen (:ID1, :ID2, etc.). Dann musst du allerdings jedem Parameter den entsprechenden Wert zuweisen.

Die Lösung mit den Variabeln finde ich jedoch übersichtlicher und einfacher:

Code:
DECLARE @ID integer
DECLARE @Name varchar(20)
SET @ID = :ID
SET @Name = :Name
DECLARE @TRANSE CHAR(8) = 'Transe00';
BEGIN TRANSACTION @TRANSE;
IF NOT EXISTS(SELECT * FROM ST_VKL WHERE ID=@ID)
INSERT INTO ST_VKL (ID,NAME) VALUES(@ID,@Name)
ELSE
UPDATE ST_VKL SET NAME=@Name WHERE ID=@ID;
IF @@ERROR = 0
COMMIT TRANSACTION @TRANSE
ELSE
ROLLBACK TRANSACTION @TRANSE;
Für die Typen von ID und Name benutzt du natürlich das was du brauchst. Da du diese Information nicht geliefert hast, musste ich irgendwas erfinden...

Übrigens würde ich die Parameter nicht mit @ deklarieren. Das @ Symbol wird von SQL für Variablen verwendet, wenn du das von Delphi aus machst genügt :VariabelName.
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#5

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 14:24
Du schreibt, dass das ein vereinfachtes Beispiel ist. Durch welches Statement wird den die PK-Verletzung durchgeführt? Ich denke es wird durch das UPDATE erzeugt, nicht durch das INSERT. Aber durch das UPDATE kann nur dann ein Fehler entstehen, wenn im SET-Teil auch die PK-Spalte(n) mit verändert werden. Es wäre also hilfreich, wenn du nicht zu viel vereinfachst, an deinem Beispiel. Dann können wir dir besser helfen.
  Mit Zitat antworten Zitat
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#6

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 14:56
die Verinfachung war natürlich nicht fehlerbehaftet, der PK besteht nur aus der ID
er macht tatsächlich ein Insert (habe den PK weggenommen und siehe da, ich habe 2 Datensätze)
das Problem ist, dass der Select innerhalb des exists nichts matched, obwohl der Datensatz da ist
ich habe sogar noch ein Convert um die Spalte und um den Parameter drumrumgebaut, dass da nix schief gehen kann, leider ohne Erfolg
ich glaube, er löst den Parameter an der stelle einfach nicht auf...

den Hinweis mit der unterschiedlichen Namensgebung für die Parameter kam auch von einem Kollegen, habe ich umgesetzt
(i für insert, u für update, w für where davor)

das @ kam tatsächlich dadurch rein, dass ich dachte, er würde intern eben genau das machen,
also die Variablen declaren, wodurch sie das @ bräuchten und dann mit den parameterwerten befüllen
da er es anscheinend nicht so macht, nehme ich das @ jetzt raus

ich werde den declare-Ansatz mal weiterverfolgen, vielen Dank dafür!!!
  Mit Zitat antworten Zitat
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#7

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 15:30
DECLARE @Transe CHAR(8) = 'Transe00';
BEGIN TRANSACTION @Transe;
DECLARE @ID INT;
SET @ID=:WID;
IF (EXISTS(SELECT * FROM ST_VKL WHERE ID=@ID))
UPDATE ST_VKL SET NAME=:UNAME
WHERE ID=@ID
ELSE
INSERT INTO ST_VKL
(ID,NAME)
VALUES(:IID,:INAME);
IF @@ERROR = 0
COMMIT TRANSACTION @Transe
ELSE
ROLLBACK TRANSACTION @Transe;

so sieht es jetzt aus.
ich habe das declare nur für die parameter gemacht, die im where verwendet werden, also zum PK gehören,
weil ich allgemein (=ohne die spezifische table zu kennen) nur für die garantieren kann, dass sie integer sind

es hat leider nicht funktioniert :/
  Mit Zitat antworten Zitat
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#8

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 16:46
toll, jetzt habe ich im insert auch mal @ID statt :IID verwendet und setzen tu ich wie folgt:
SET @ID = CONVERT(INT,:WID);
Der Parameter WID hat den Wert 1699, inserten tut er mir aber den Wert -1, wie geht das denn?

ele, da du das offenbar shconmal zum laufen gekriegt hast, die frage an dich: was mache ich falsch? ich hab's eigentlich genau so gemacht wie du

Geändert von hyype (12. Jun 2012 um 16:53 Uhr)
  Mit Zitat antworten Zitat
NormanNG

Registriert seit: 1. Feb 2006
294 Beiträge
 
Delphi 2007 Professional
 
#9

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 16:59
Hi,

erstelle eine StoredProc in der Datenbank, der du alle zu speichernden Werte als Parameter übergibst. In der Proc kannst du dann so ähnlich wie bisher zuerst update und ggf. insert ausführen.

In Delphi hast du dann nur einmal die Parameter - alle Logik liegt in der Datenbank.
Gruß
Norman
  Mit Zitat antworten Zitat
hyype

Registriert seit: 5. Nov 2008
97 Beiträge
 
Delphi XE2 Professional
 
#10

AW: TADOCommand mit Parametern - PK-Verletzung

  Alt 12. Jun 2012, 17:07
Das Problem ist, dass ich das sehr allgemein programmiere, um es für jede Tabelle zu benutzen.
Die spezifischen Tabellen haben dann unterschiedliche Anzahl an Spalten, unterschiedliche Datentypen etc
Da ich die alle machen, kann ich nur sagen, dass die von mir als PK gekennzeichneten Spalten integer sind.
Über den Rest ist mir auf der Ebene nix bekannt, daher weise ich die Werte als Variant zu, also

var value : variant;
...
value := 1699;
...
params[i].value := value;

und:

Delphi-Quellcode:

  q := tadodataset.create(nil);
  try
    q.connectionstring := ...
    q.CommandType := cmdText;
    q.commandtext := 'DECLARE @BLUB INT; SET @BLUB = :BLUB; SELECT @BLUB AS BLUB;';
    q.Parameters.parambyname('BLUB').value := 1699;
    q.Open;
    showmessage(inttostr(q.fieldbyname('blub').asinteger));
  finally
    freeandnil(q);
  end;
das geht komischerweise, ja bin ich denn blöd?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz