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

  • megaprogrammer
    hat ein Thema erstellt Insert foreign key.

    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^^

  • rkr
    antwortet
    Das ist keine Frage der Vorliebe. Und Transaktionen brauche ich dafür auch nicht. Timestamps sind schlicht überflüssig und bieten keinen Sicherheitsgewinn. Im Gegenteil. Auf diese Weise kann ich sehr wohl auch doppelte Schlüssel erzeugen. Der Timestamp macht es lediglich etwas unwahrscheinlicher.

    Wenn schon ein so kurzer Zeitraum wie in deinem Skript zu erahnen ist ausreicht um einen doppelten Schlüssel zu erzeugen, dann wirst du auch praktisch immer den gleichen Zeitstempel dabei haben.

    Du kannst das ja für deinen Privatspass so machen, aber empfehle anderen so einen Schwachsinn nicht.

    Einen Kommentar schreiben:


  • ChristianK
    antwortet
    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?

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    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

    Einen Kommentar schreiben:


  • rkr
    antwortet
    Wozu gibt es dann autoincrement-keys*?


    * heissen in anderen Datenbanken möglicherweise anders :P

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    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 .'

    Einen Kommentar schreiben:


  • ChristianK
    antwortet
    Ja schön. Oder du verwendest Transaktionen. Das wäre der korrekte Weg.

    Einen Kommentar schreiben:


  • Gast-Avatar
    Ein Gast antwortete
    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.

    Einen Kommentar schreiben:


  • akretschmer
    antwortet
    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)

    Einen Kommentar schreiben:


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

    Einen Kommentar schreiben:


  • akretschmer
    antwortet
    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.

    Einen Kommentar schreiben:


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

    Einen Kommentar schreiben:


  • akretschmer
    antwortet
    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.

    Einen Kommentar schreiben:


  • rkr
    antwortet
    Nimm dann gleich auch "Isolationslevel" mit.

    Einen Kommentar schreiben:


  • G.Schuster
    antwortet
    last insert id.

    Einen Kommentar schreiben:

Lädt...
X