Ankündigung

Einklappen
Keine Ankündigung bisher.

MySQL: INSERT INTO oder UPDATE verknüpft in einem Query

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Gast-Avatar
    Ein Gast erstellte das Thema MySQL: INSERT INTO oder UPDATE verknüpft in einem Query.

    MySQL: INSERT INTO oder UPDATE verknüpft in einem Query

    Hey,

    wollte mal wissen ob es möglich ist in einem Query entweder INSERT INTO auszuführen (falls Eintrag noch nicht vorhanden) oder UPDATE (falls eintrag vorhanden) auszuführen.

    Das ganze jedoch OHNE on duplicate key entry, da es sich bei den Spalten nicht um Prim. Keys handelt.

    Tabellen Struktur sieht folgendermaßen aus:

    `id` - `attribute` - `val`

    Für alle IDs können verschiedene Attribute u. Werte gespeichert werden:

    Code:
    ID | attribute | val
    1    Attr_1        2
    1    Attr_2        5
    2    Attr_5        6
    2    Attr_8        1
    Nun möchte ich z.B. für ID 1 das Attribut 1 um 5 als auch für ID 2 (default value ist 0 von daher wäre es also 0+5) mit demselben Query erhöhen können, da ich im vorhinein nicht mit einem extra Query überprüfen möchte ob die Zeile bereits existiert.

    Hab ebenfalls REPLACE gegoogelt, allerdings kann ich da nicht mit WHERE arbeiten.

    Ist es generell möglich das zu tun oder muss ich z.B. zunächst ein UPDATE query ausführen und falls keine Zeilen betroffen sind ein INSERT INTO hinterher schmeißen?

    Vielen Dank im Vorraus.

  • Gast-Avatar
    Ein Gast antwortete
    Bei mir kommt kein Ergebnis - die procedure wird also nicht gespeichert. Ich habe in einigen Threads gelesen, dass das an einer fehlerhaften Installation oder an falschen Tabellenrechten liegt.

    Ich werde dem mal nachgehen, da mich diese prodecures sehr interessieren und ich (dank Dir) einen schnellen Einstieg in die Materie bekommen habe. Das Problem werde ich - denke ich - aber mit ON DUPLICATE KEY UPDATE lösen, da das nun dank niko auch funktioniert.

    Nochmal vielen Dank für die viele Zeit die Du dir genommen hast mir procedures nahe zu bringen .

    Grüße

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Zitat von juice122 Beitrag anzeigen
    Mit exakt deinem Code und einem

    CALL example_proc(); oder CALL db.example_proc(); dahinter kommt einfach nur:
    Bei mir sieht es so aus:

    Code:
    Server version: 5.1.44-community MySQL Community Server (GPL)
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> CALL example_proc();
    Query OK, 1 row affected (0.86 sec)
    
    mysql>
    so sieht es bei mir aus, wenn ich die "falsche" Datenbank verwende.
    Code:
    mysql> CALL test22.example_proc();
    ERROR 1305 (42000): PROCEDURE test22.example_proc does not exist
    mysql>
    so kannst Du prüfen, ob die Stored Procedure wirklich (unter der aktuellen Connection und Datenbank) existiert:
    Code:
    mysql> show procedure status like 'ex%';
    +-----------+--------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
    | Db        | Name         | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
    +-----------+--------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
    | testdb    | example_proc | PROCEDURE | root@localhost | 2010-05-05 22:33:40 | 2010-05-05 22:33:40 | DEFINER       |         | latin1               | latin1_swedish_ci    | latin1_swedish_ci  |
    +-----------+--------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
    1 row in set (0.04 sec)
    
    mysql>
    Ich habe die Procedure als "root"-user erzeugt.

    Grüße
    Thomas

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Zitat von ChrisB Beitrag anzeigen
    Es gibt die Prozedur, die du aufrufen möchtest, nicht - also wird wohl bei deren Erstellung was schief gegangen sein. Hast du also diese Stelle mal überprüft ...?
    Wenn ich nur die Prodezur erstelle erhalte ich folgendes Ergebnis:

    Ihr SQL-Befehl wurde erfolgreich ausgeführt. ( die Abfrage dauerte 0.0032 sek. )

    Zitat von nikosch
    ...
    Hat jetzt komischerweise bei ner komplett neuen Tabelle geklappt. Danke dir.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Code:
    CREATE TABLE ... PRIMARY KEY(Feld1,Feld2)

    Einen Kommentar schreiben:


  • ChrisB
    antwortet
    Zitat von juice122 Beitrag anzeigen
    Mit exakt deinem Code und einem

    CALL example_proc(); oder CALL db.example_proc(); dahinter kommt einfach nur:

    #1305 - PROCEDURE db.example_proc does not exist.
    Habs auf zwei Servern versucht, beide mit ALL PRIVILEGES als Rechte... ne Idee was da los sein könnte?
    Es gibt die Prozedur, die du aufrufen möchtest, nicht - also wird wohl bei deren Erstellung was schief gegangen sein. Hast du also diese Stelle mal überprüft ...?

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Datentypen sind bei mir alle INT, sorry meine Tabelle im ersten Post is mir da einfach missglückt. Ich bin aber leider immer noch nicht am Ziel.

    Mit exakt deinem Code und einem

    CALL example_proc(); oder CALL db.example_proc(); dahinter kommt einfach nur:

    #1305 - PROCEDURE db.example_proc does not exist.
    Habs auf zwei Servern versucht, beide mit ALL PRIVILEGES als Rechte... ne Idee was da los sein könnte?

    Zitat von nikosch
    Nein. Auch Schlüssel über mehrere Felder sind möglich, auch als PK.
    Könntest du mir das entsprechende Query zeigen. Wenn ich es versuche (siehe 3 Posts weiter oben) komme ich nicht zu dem gewünschten Ergebnis.

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Zitat von juice122 Beitrag anzeigen
    Ich verstehs grad einfach nicht und googlen hat nichts geholfen.
    Vielleicht solltest Du mal bei Yahoo googlen...

    Also da sind einfach viele kleine Fehler drin, ansonsten sieht es ganz gut aus.

    Code:
    CREATE TABLE table1 (
     id VARCHAR(5),
     attribute VARCHAR(5),
     val VARCHAR(5)
    );
    
    
    Delimiter $$ 
    CREATE PROCEDURE example_proc( )  
    BEGIN 
     Declare nExists INT;
    
     SELECT COUNT(*)
       INTO nExists
       FROM table1
       WHERE val ='5'
         AND attribute='2'
         AND id = '2';
     
     IF nExists THEN 
       UPDATE table1 
          SET val = val + '8' 
        WHERE val ='5' 
          AND attribute='2' 
          AND id = '2';
     
     ELSE 
       INSERT INTO table1
       ( id, attribute, val ) VALUES
       ( '2', '2', '8' );
     END IF;
    END$$
    
    DELIMITER ;
    Läuft bei mir jetzt so durch, habe es aber nicht weiter probiert.

    Hier
    Code:
          SET val = val + '8' 
    noch mal überlegen, ob es eine Addition werden soll oder nicht. Als Datentyp wäre INT besser als VARCHAR, denke ich mal.


    Grüße
    Thomas

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Hm, könntest Du mir sagen, wie das Query dann aussehen muss? Ich hab jetzt sowohl `id` als auch `attribute` als PRIMARY KEY gesetzt.

    Hier nochmal ne Bsp.Tabelle:

    Code:
    ID | attribute | val
    1         1          2
    1         2          3
    2         2          5
    2         3          4
    Query:

    INSERT INTO table (id, attribute, val) VALUES(1, 1, 5) ON DUPLICATE KEY UPDATE val = val + 5
    (Das alle rows vom UPDATE betroffen wären ist erstmal egal.)

    Allerdings wird nun nicht geupdated sondern eine neue Zeile mit den Werten vom INSERT INTO eingefügt.

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Schließt das die Verwendung von Keys nicht aus?
    Nein. Auch Schlüssel über mehrere Felder sind möglich, auch als PK.

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Zitat von nikosch Beitrag anzeigen
    Ich würde auf jeden Fall, mal drüber nachdenken (bzw. erfahren wollen) warum Du keine Keys verwenden kannst. Bspw. über (ID , attribute) sollte das doch möglich sein. Ansonsten erkenne ich nämlich keinen Sinn in diesem Beispiel, weil dann UPDATE oder INSERT ja ziemlich willkürlich wäre.
    Naja, sowohl ID als auch Attribute können mehrfach auftreten. Schließt das die Verwendung von Keys nicht aus?

    Zitat von thomas_w
    ...
    Sorry, muss nochmal nerven:

    Hab jetzt ne Procedure nach diesem Beispiel (MySQL :: MySQL 5.1 Reference Manual :: 12.7.4.2 DECLARE for Handlers) aufgebaut:

    Code:
    CREATE PROCEDURE p ()
    BEGIN
      DECLARE i INT DEFAULT 3;
      retry:
        REPEAT
          BEGIN
            DECLARE CONTINUE HANDLER FOR SQLWARNING
              BEGIN
                ITERATE retry;  # illegal
              END;
          END;
          IF i < 0 THEN
            LEAVE retry;        # legal
          END IF;
          SET i = i - 1;
        UNTIL FALSE END REPEAT;
    END;
    Sieht folgendermaßen aus:

    Code:
    Delimiter $$ CREATE PROCEDURE example_proc( )  BEGIN Declare var INT;
    
    SELECT `id`
    INTO var
    FROM table
    WHERE val ='5'
    AND attribute='2'
    AND id = '2';
    
    IF var THEN UPDATE table SET val = val + '8' WHERE val ='5' AND attribute='2' AND id = '2';
    
    ELSE INSERT INTO table( id, attribute, val ) value(
    '2',
    '2',
    '8'
    );
    end if;
    end;
    $$
    Problem:

    #1327 - Undeclared variable: test
    Ich verstehs grad einfach nicht und googlen hat nichts geholfen.

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    da so ein Trigger oder Stored Procedure in der Datenbank abläuft, fällt die komplette Übertragung (von PHP zur Datenbank) und das SQL-Parsing weg. Damit sollte eine SP schneller sein als reines SQL. Aber (aus-)probieren geht vor studieren...

    Viel Erfolg!

    Grüße
    Thomas

    Einen Kommentar schreiben:


  • nikosch
    antwortet
    Ich würde auf jeden Fall, mal drüber nachdenken (bzw. erfahren wollen) warum Du keine Keys verwenden kannst. Bspw. über (ID , attribute) sollte das doch möglich sein. Ansonsten erkenne ich nämlich keinen Sinn in diesem Beispiel, weil dann UPDATE oder INSERT ja ziemlich willkürlich wäre.

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Alles klar dann probier ich mal das Beispiel aus und vergleich die Laufzeiten.

    Weißt du wie's da ist mit dem Ressourcenverbrauch? Ist der ungemein höher oder braucht man sich darüber eher keine Gedanken machen?

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    Zitat von juice122 Beitrag anzeigen
    würde das ganze auf eine IF THEN Anweisung rauslaufen?
    Sinngemäß ja, aber MySQL kann diese Syntax nicht. Bleibt also der
    sogenannte Trigger.

    komplettes Beispiel aus dem Handbuch (suche mal nach CREATE TRIGGER oder CREATE PROCEDURES)
    Code:
    In MySQL 5.1, you can write triggers containing direct references to tables by name, such as the trigger named testref shown in
    this example:
    
    CREATE TABLE test1(a1 INT);
    CREATE TABLE test2(a2 INT);
    CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
    CREATE TABLE test4(
    a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    b4 INT DEFAULT 0
    );
    
    delimiter |
    
    CREATE TRIGGER testref BEFORE INSERT ON test1
    FOR EACH ROW BEGIN
    INSERT INTO test2 SET a2 = NEW.a1;
    DELETE FROM test3 WHERE a3 = NEW.a1;
    UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
    END;
    
    |
    delimiter ;
    
    INSERT INTO test3 (a3) VALUES
    (NULL), (NULL), (NULL), (NULL), (NULL),
    (NULL), (NULL), (NULL), (NULL), (NULL);
    INSERT INTO test4 (a4) VALUES
    (0), (0), (0), (0), (0), (0), (0), (0), (0), (0);
    
    Suppose that you insert the following values into table test1 as shown here:
    
    mysql> INSERT INTO test1 VALUES
    -> (1), (3), (1), (7), (1), (8), (4), (4);
    Query OK, 8 rows affected (0.01 sec)
    Records: 8 Duplicates: 0 Warnings: 0
    Trigger lassen sich in etwa mit Datenbank-Ereignissen gleichsetzen. Nach dem Motto: "Wenn INSERT oder UPDATE oder DELETE auf dieser Tabelle, dann mach dies.."

    Trigger und Stored Procedures sind eine eigene SQL-Sprache in der Datenbank und damit "eine eigene Welt".

    Grüße
    Thomas

    Einen Kommentar schreiben:

Lädt...
X