Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12
  1. #1

    [SQL]: Una INSERT impossibile?

    Salve.

    In un database MySQL ho una tabella con i seguenti campi:
    codice:
    TABLE `pulsanti` (
      `id` bigint(20) unsigned NOT NULL auto_increment,
      `nome` varchar(30) NOT NULL default '',
      `ord` bigint(20) NOT NULL default '0',
    )
    E' possibile, con una singola istruzione SQL, inserire un nuovo elemento con ord=id, oppure fare in modo che per default ord sia uguale alla chiave autoincrementata?

    In pratica vorrei realizzare:

    codice:
    INSERT INTO `pulsanti` (`nome`) VALUES ('prova')
    
    SELECT `id` AS inserito FROM `pulsanti` WHERE (`nome`='prova')
    
    UPDATE `pulsanti` SET (`ord`=inserito)
    in una unica istruzione, per evitare gli ovvi problemi di queste query.

    E' possibile?
    Grazie!
    Salvatore De Bonis AKA Novice of Ricotta AKA NashCrash

  2. #2
    sicuramente invece di 3 ne puoi fare due con mysql_insert_id

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2001
    Messaggi
    525
    INSERT INTO `pulsanti` (`nome`) VALUES ('prova')

    $id_generato=mysql_insert_id();

    UPDATE `pulsanti` SET (`ord`='$id_generato')

  4. #4
    Si questo lo so!
    Ma non volevo tornare alla pagina PHP.

    Se due utenti A e B eseguono contemporaneamente il codice:
    codice:
    1) INSERT INTO `pulsanti` (`nome`) VALUES ('prova') 
    
    2) $id_generato=mysql_insert_id(); 
    
    3) UPDATE `pulsanti` SET (`ord`='$id_generato')
    visto che richiamano la stessa pagina PHP, potrebbe succedere che una esecuzione concorrente sia del tipo:

    codice:
    A1) INSERT INTO `pulsanti` (`nome`) VALUES ('prova') id=3
    B1) INSERT INTO `pulsanti` (`nome`) VALUES ('prova') id=4
    A2) $id_generato=mysql_insert_id();                  id=4 e non 3
    B2) $id_generato=mysql_insert_id();                  id=4
    A3) UPDATE `pulsanti` SET (`ord`='$id_generato')     ord=4
    B3) UPDATE `pulsanti` SET (`ord`='$id_generato')     ord=4
    dove con An ho indicato la riga n-ma eseguita dall'utente A.
    Un simile ordine temporale dell'esecuzione su database delle istruzioni sarebbe estremamente pernicioso, per la conseguente inconsistenza del database.

    Questo perché PHP chiede a MySQL di fare la insert e poi lo libera, permettendo ad altri di fare una ulteriore INSERT, prima che l'istruzione mysql_insert_id() possa raccogliere il corretto id.
    Si, lo so, è un caso limite! Praticamente A e B devono far eseguire il codice contemporaneamente, ma io preferisco programmare bene e non tralasciare niente!

    Se invece l'istruzione fosse una sola, eseguita interamente da MySQL non si avrebbe inconsistenza.

    Potrei usare le transazioni, ma per una cosa così, preferisco adottare altri escamotage...

    Possibile che non ci sia metodo?
    Salvatore De Bonis AKA Novice of Ricotta AKA NashCrash

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2001
    Messaggi
    525
    No, non c'è modo di fare un'inserimento e contemporaneamente inserire anche l'id autoincrementato....che io sappia.
    Le soluzioni sono due....
    Ad ogni insert devi far seguire subito la funzione che legge l'id_generato:

    A1) INSERT INTO `pulsanti` (`nome`) VALUES ('prova') id=3
    A2) $id_generato=mysql_insert_id(); id=3
    A3) UPDATE `pulsanti` SET (`ord`='$id_generato') ord=3

    B1) INSERT INTO `pulsanti` (`nome`) VALUES ('prova') id=4
    B2) $id_generato=mysql_insert_id(); id=4
    B3) UPDATE `pulsanti` SET (`ord`='$id_generato') ord=4

    ...certo, la probabilità che si inserisca un utente nel mezzo c'è...ma penso sia bassa.

    L'altra soluzione è di implementare un sistema che evita di registrare un utente quando c'è una procedura di inserimento in corso.... che magari viene rilevata settando un flag su un db all'accesso del primo utente alla pagina di memorizzazione dati...e modificando di nuovo il flag a termine dell'operazione di memorizzazione dati sul db...tipo 'lock' della tabella

  6. #6
    codice:
    INSERT INTO `pulsanti` (`nome`) VALUES ('prova');
    
    UPDATE pulsanti set ord = id 
    where id = last_insert_id();
    mi pare faccia al caso tuo...

    Il silenzio è spesso la cosa migliore. Pensa ... è gratis.

  7. #7
    Utente di HTML.it
    Registrato dal
    Sep 2002
    Messaggi
    460
    Spero che tu non stia utilizzando l'id per determinare l'ordine di inserimento. Se si, ti strappo le braccine.

    Se questo e' quello che vuoi fare, e lo credo proprio, usa un campo timestamp e lo imposti a NOW().

    Una volta ancora: le chiavi surrogate non vanno mai usate per null'altro se non essere chiavi surrogate. Attribuire qualunque altro significato e' errato e pericoloso.
    There are 10 types of people in the world - those who understand binary and those who don't.

  8. #8
    Originariamente inviato da frinkia
    Spero che tu non stia utilizzando l'id per determinare l'ordine di inserimento. Se si, ti strappo le braccine.
    E me le farei strappare....

    Ovviamente no! La mia domanda era più teorica che pratica...

    Cmq credo che la risposta sia "non si può fare!" anche se la seconda idea di Simoxxx (che mi sa tanto di transazioni... ) sia abbordabile...

    Grazie a tutti!
    Salvatore De Bonis AKA Novice of Ricotta AKA NashCrash

  9. #9
    Si puo' fare... si puo'.


    Il silenzio è spesso la cosa migliore. Pensa ... è gratis.

  10. #10
    Originariamente inviato da piero.mac
    codice:
    INSERT INTO `pulsanti` (`nome`) VALUES ('prova');
    
    UPDATE pulsanti set ord = id 
    where id = last_insert_id();
    mi pare faccia al caso tuo...
    Avevi ragione Piero!!! Si può fare, ma non come hai scritto tu, bensì:

    codice:
    INSERT INTO `pulsanti` (`nome`,`ord`) VALUES ('', LAST_INSERT_ID());
    Non avevo visto bene il tuo codice...

    Grazie!
    Salvatore De Bonis AKA Novice of Ricotta AKA NashCrash

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.