Ankündigung

Einklappen
Keine Ankündigung bisher.

Insert foreign key

Einklappen

Neue Werbung 2019

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

  • Insert foreign key

    Hihu

    Ich habe eine Konzeptionelle Frage. Also ich habe ein Programm geschrieben das über mehrere Tabellen INSERTS macht. Zum Beispiel INSERT into data irgendwelche Values und danach insert into data2 wo es einen fremdschlüssel benutzt nähmlich den letzen eingetrage id bei der ersten tabelle. alles schön und gut solange die applikation localhost ist. aber im internet funken mir andere leute herein.

    Kurz:
    Das PROBLEM ist also das ich nicht einfach den letzen PK einer Tabelle (max) nehmen kann und diesen beim nächsten insert als Fremdschlüssel verwenden. was ist wenn jemand dazwischenfunkt?

    Gibt es da irgendwelche Methoden um das zu verhindern
    SPRICH: gewährleisten das der nächste insert tatsächlich die id des vorherigen nimmt (als FK)

    oder inserts über 2 tabellen?

    Hatt jemand irgendwelche stichworte dazu oder methoden in die ich mich einlesen kann?

    danke für die antworten^^

  • #2
    Transaktionen.
    [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

    Kommentar


    • #3
      last insert id.
      VokeIT GmbH & Co. KG - VokeIT-oss @ github

      Kommentar


      • #4
        Nimm dann gleich auch "Isolationslevel" mit.

        Kommentar


        • #5
          Zitat von megaprogrammer Beitrag anzeigen

          Hatt jemand irgendwelche stichworte dazu oder methoden in die ich mich einlesen kann?

          danke für die antworten^^
          Welche DB? In PostgreSQL kannst Du currval() nutzen oder gleich wCTE einsetzen, dann sind Deine 2 oder mehr Inserts nur 1 (EIN!) Befehl. MySQL hat last_insert_id() oder so ähnlich. Schau in die Doku. Max() jedenfalls ist prinzipiell falsch.
          PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

          Kommentar


          • #6
            @akretschma
            Kannst du currval() und wCTE jeweils mit einer sinnvollen Ressource verlinken?

            Kommentar


            • #7
              Zitat von rkr Beitrag anzeigen
              @akretschma
              Kannst du currval() und wCTE jeweils mit einer sinnvollen Ressource verlinken?
              Die Doku http://www.postgresql.org/docs/9.3/s...-sequence.html und ein kleines Beispiel für wCTE:

              Code:
              test=# create table master (id serial primary key, val text);
              CREATE TABLE
              test=*# create table slave(master_id int references master, val text);
              CREATE TABLE
              test=*# with foo as (insert into master (val) values ('master 1') returning id) insert into slave select foo.id, 'slave 1' from foo;
              INSERT 0 1
              test=*# select * from master;
               id |   val
              ----+----------
                1 | master 1
              (1 row)
              
              test=*# select * from slave;
               master_id |   val
              -----------+---------
                       1 | slave 1
              (1 row)
              Ich nenne NIRGENDS die ID und schicke nur EIN Statement an den Server. Das ganze ist ausbaufähig auch auf mehr als nur einen Datensatz, der in Slave reinkommen soll, beispielsweise. Insbesondere Masseninserts können davon deutlich profitieren, spart Zeit.
              PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

              Kommentar


              • #8
                Kann ich in diesem wCTE-Statement mehr als ein Insert verbauen? Wie sähe das dann ungefähr aus?

                Kommentar


                • #9
                  Zitat von rkr Beitrag anzeigen
                  Kann ich in diesem wCTE-Statement mehr als ein Insert verbauen? Wie sähe das dann ungefähr aus?
                  Klar:

                  aktueller Stand:
                  Code:
                  test=# select * from person;
                   id | name
                  ----+------
                  (0 rows)
                  
                  test=*# select * from phone ;
                   p_id | nummer
                  ------+--------
                  (0 rows)
                  
                  test=*# select * from mail ;
                   p_id | mail
                  ------+------
                  (0 rows)
                  test=*# select currval('person_id_seq');
                   currval
                  ---------
                         3
                  (1 row)
                  Nun 1 Befehl und der neue Stand:

                  Code:
                  test=*# with p as (insert into person (name) values ('person1') returning id), ph as (insert into phone (select p.id, 'nummer1' from p union select p.id, 'nummer2' from p)), m as (insert into mail (select id, 'mail1' from p union all select id, 'mail2' from p)) select 'habe alles fertig';
                       ?column?
                  -------------------
                   habe alles fertig
                  (1 row)
                  
                  test=*# select * from person;
                   id |  name
                  ----+---------
                    4 | person1
                  (1 row)
                  
                  test=*# select * from phone ;
                   p_id | nummer
                  ------+---------
                      4 | nummer1
                      4 | nummer2
                  (2 rows)
                  
                  test=*# select * from mail ;
                   p_id | mail
                  ------+-------
                      4 | mail1
                      4 | mail2
                  (2 rows)
                  PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                  Kommentar


                  • #10
                    ich hab die Erfahrung gemacht, wenn zeitgleich mehr als ein Mitarbeiter INSERT verursachen kann
                    das mit Timestamp's zu versehen und expleziet diesen timestamp in die WHERE Klausel mit einbringen.

                    Sprich eine extra Spalte " TIME_of_CREAT "
                    Hat mir zum einen viel CODE gespart und ich hatte damit immer ein eindeutigen SELECT
                    vor, wärend und nach dem INSERT

                    Egal wieviel USER gleichzeitig INSERT`s durchführen.

                    Kommentar


                    • #11
                      Ja schön. Oder du verwendest Transaktionen. Das wäre der korrekte Weg.
                      [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                      Kommentar


                      • #12
                        Zitat von ChristianK Beitrag anzeigen
                        Ja schön. Oder du verwendest Transaktionen. Das wäre der korrekte Weg.
                        Code:
                        -- start a new transaction
                        start transaction;
                         
                        -- get latest order number
                        select @orderNumber := max(orderNUmber)
                        from orders;
                        -- set new order number
                        set @orderNumber = @orderNumber  + 1;
                         
                        -- insert a new order for customer 145
                        insert into orders(orderNumber,
                                           orderDate,
                                           requiredDate,
                                           shippedDate,
                                           status,
                                           customerNumber)
                        values(@orderNumber,
                               now(),
                               date_add(now(), INTERVAL 5 DAY),
                               date_add(now(), INTERVAL 2 DAY),
                               'In Process',
                                145);
                        -- insert 2 order line items
                        insert into orderdetails(orderNumber,
                                                 productCode,
                                                 quantityOrdered,
                                                 priceEach,
                                                 orderLineNumber)
                        values(@orderNumber,'S18_1749', 30, '136', 1),
                              (@orderNumber,'S18_2248', 50, '55.09', 2);
                        -- commit changes    
                        commit;      
                         
                        -- get the new inserted order
                        select * from orders a
                        inner join orderdetails b on a.ordernumber = b.ordernumber
                        where a.ordernumber = @ordernumber;
                        VS
                        SQL erweitern
                        , $timestamp
                        Code:
                        WHERE timestamp = ' . $timestamp .'

                        Kommentar


                        • #13
                          Wozu gibt es dann autoincrement-keys*?


                          * heissen in anderen Datenbanken möglicherweise anders :P

                          Kommentar


                          • #14
                            Zitat von rkr Beitrag anzeigen
                            Wozu gibt es dann autoincrement-keys*?


                            * heissen in anderen Datenbanken möglicherweise anders :P
                            Ich hab ja nicht gesagt, dass eine, durch mysql selbst gesetze, id schlecht ist.
                            habe lediglich empfohlen, durch ein timestamp, die umständliche wege der transaktion zu umgehen.

                            punkt

                            wenn dein persönliches empfinden die transaktion vorzieht. ist das eben so.
                            ich ess gern Apfel und trink zirtone

                            Kommentar


                            • #15
                              Ne sorry, die letzten drei Beiträge von dir in diesem Forum glänzen nur so von Inkompetenz.

                              Was bitteschön ist komplizierter an einer Transaktion als einer zusätzlichen Tabelle und eigenen Inkrementen und eigener Implementation con Transaktion?
                              [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

                              Kommentar

                              Lädt...
                              X