![]() |
Datenbank: MSSQL2008R2 • Version: ? • Zugriff über: ADO
TADOCommand mit Parametern - PK-Verletzung
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... |
AW: TADOCommand mit Parametern - PK-Verletzung
Warum verwendest du nicht das vorhandene
![]() |
AW: TADOCommand mit Parametern - PK-Verletzung
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... |
AW: TADOCommand mit Parametern - PK-Verletzung
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:
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...
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; Ü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. |
AW: TADOCommand mit Parametern - PK-Verletzung
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.
|
AW: TADOCommand mit Parametern - PK-Verletzung
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!!! |
AW: TADOCommand mit Parametern - PK-Verletzung
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 :/ |
AW: TADOCommand mit Parametern - PK-Verletzung
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 |
AW: TADOCommand mit Parametern - PK-Verletzung
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. |
AW: TADOCommand mit Parametern - PK-Verletzung
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:
das geht komischerweise, ja bin ich denn blöd?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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz