insert_id
Mijn onbegrip betreffende PHP is groot, dat geef ik graag toe.
Dus als jij mij kan uitleggen waarom de insert_id na een insert (IF) last zou hebben van een update code (ELSE) ergens anders ben ik weer een stap verder. Is er een geheime afspraak dat er geen tekens in de brontekst mogen staan tussen de insert en insert_id?
de testcode was:
if ($id === 9999) $p = $db->query($qInsert);
else $p = $db->query($qUpdate);
$id = $db->insert_id;
Paul Ulje op 18/09/2016 19:44:07:
Het hele eiereneten is dat je in de UPDATE een bestaand record bijwerkt met een bestaande en bekende id. De nieuwe, tot dan nog onbekende id heb je alleen nodig wanneer je met INSERT een nieuw record toevoegt.
Stel, je gebruikt de id voor een klantnummer. Bij het toevoegen van een nieuwe klant met INSERT krijgt die klant een nieuw klantnummer dat pas bekend is na het uitvoeren van de query. Wijzig je echter de gegevens van een bestaande klant, dan gebruik je een bestaande én bekende id in de UPDATE — en heeft de laatst toegevoegde, nieuwe id in die context geen betekenis.
Ik vermoed dat je — elders in je code — wat last hebt van code smell, bijvoorbeeld doordat je de id voor twee verschillende dingen gebruikt.
Ik snap ook niet wat dat zou moeten opleveren. Google levert me alleen topics van mensen die niets terugkrijgen van deze functie en als comment krijgen dat ze ook niets inserten.
En anders niet meer dan handleidingen die weliswaar de update-query noemen als mogelijke bron voor de insert_id functie, maar niet toelichten wat je dan terug mag verwachten.
Iemand een uitleg wat insert_id zou moeten teruggegeven bij een update-query? Enige wat ik me namelijk voor zou kunnen stellen, is een trigger die bij een update afgaat en dan wat insert. Maar dan zou dat ook bij een DELETEquery moeten werken.
@Paul
Waarom zou je die id opvragen als je hem vooraf al weet?
W3Schools zegt:
If we perform an INSERT or UPDATE on a table with an AUTO_INCREMENT field, we can get the ID of the last inserted/updated record immediately: $last_id = $conn->insert_id;
@Paul
Waarom zou je die id opvragen als je hem vooraf al weet?
Inderdaad Ivo. Ik zou het niet weten. Maar wie beweert er dan ook dat ik het id wil opvragen als ik hem al weet? Ik niet. Lees de draad en verbaas je net als ik over die vreemde aanname van sommigen.
Ik heb drie regeltjes gemaakt om de bewering van W3Schools te testen. En dan blijkt het niet te werken.
Waarom niet? Géén idee. Ook niet na de hulp van SanThe. Nou, dan haal ik die id wel op een andere manier op na een insert. Ik zie daar geen probleem in. Maar een aantal PHPers is het daar niet mee eens.
Gewijzigd op 22/09/2016 16:12:42 door Paul Ulje
Paul Ulje op 22/09/2016 16:11:53:
Ik heb drie regeltjes gemaakt om de bewering van W3Schools te testen. En dan blijkt het niet te werken.
Dat is helaas bekend. Vandaar dat ze vaak "W3Fools" worden genoemd.
Er is zelfs een website aan besteed.
Voor beweringen die veel dichter bij de waarheid liggen, kun je beter 'RTFM' in de documentatie duiken, in dit geval bijvoorbeeld die van PDO::lastInsertId voor PHP.
http://php.net/manual/en/mysqli.insert-id.php
heeft het ook over update.
"The mysqli_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute, this function will return zero. "
echter: heeft het ook over update.
"The mysqli_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute, this function will return zero. "
een UPDATE het aantal affected rows.
Als je niets toevoegt maar meerdere records wijzigt, en je de update-volgorde dan ook nog eens kunt wijzigen met een ORDER BY, wat is dan nog de betekenis van de last_insert_id()?
De TS zou ook daarom onderhand wel moeten kunnen uitleggen wat hij nou eigenlijk concreet met die id wil doen — anders dan een voorbeeld van W3Fools weerleggen, want dat die vaak niet kloppen, wisten we al.
Dat is wel atypisch gedrag, want je verwacht bij Quote:
UPDATE returns the number of rows that were actually changed. The mysql_info() C API function returns the number of rows that were matched and updated and the number of warnings that occurred during the UPDATE.
Als je niets toevoegt maar meerdere records wijzigt, en je de update-volgorde dan ook nog eens kunt wijzigen met een ORDER BY, wat is dan nog de betekenis van de last_insert_id()?
De TS zou ook daarom onderhand wel moeten kunnen uitleggen wat hij nou eigenlijk concreet met die id wil doen — anders dan een voorbeeld van W3Fools weerleggen, want dat die vaak niet kloppen, wisten we al.
Gewijzigd op 22/09/2016 17:26:59 door Ward van der Put
Gewijzigd op 22/09/2016 17:41:16 door Ben van Velzen
Ivo P op 22/09/2016 16:51:23:
echter: http://php.net/manual/en/mysqli.insert-id.php
heeft het ook over update.
"The mysqli_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute, this function will return zero. "
heeft het ook over update.
"The mysqli_insert_id() function returns the ID generated by a query on a table with a column having the AUTO_INCREMENT attribute. If the last query wasn't an INSERT or UPDATE statement or if the modified table does not have a column with the AUTO_INCREMENT attribute, this function will return zero. "
Ik gok dat dat een booboo is en dat er REPLACE wordt bedoeld in plaats van UPDATE (replace is in feite een combinatie van delete en insert).
Voor de gein ben ik eens in de sourcecode van PHP gedoken. De C-code is net iets te ingewikkeld om in een oogopslag te kunnen bepalen hoe het werkt, maar de testscripts laten duidelijk zien dat mysql(i)_insert_id() alleen wordt getest met INSERT-statements. Dat suggereert ook wel het een en ander...
Om daar echt zeker van te zijn zou je de mysql client library moeten bekijken vermoed ik, omdat deze rechtstreeks aangeroepen wordt. De logica van MySQL kennende is dit soort gedrag mogelijk zelfs afhankelijk van de sql mode.
Gewijzigd op 22/09/2016 19:03:46 door Ben van Velzen
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
$dsn = 'mysql:host=localhost;dbname=test';
$username = 'root';
$password = '';
$dbh = new \PDO($dsn, $username, $password);
$dbh->query("
CREATE TABLE IF NOT EXISTS users (
user_id SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
PRIMARY KEY pk_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci
");
// Drie records toevoegen: user_id 1, 2 en 3
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Jan'), ('Piet'), ('Joris')
");
// Je zou user_id == 3 verwachten, maar dit is: string(1) "1"
var_dump($dbh->lastInsertId());
// Record 2 bijwerken
$dbh->query("
UPDATE users
SET first_name = 'Kees'
WHERE user_id = 2
");
// We hebben niets toegevoegd: string(1) "0"
var_dump($dbh->lastInsertId());
// Nog een record toevoegen: user_id wordt 4
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Corneel')
");
// Nu wel juist: string(1) "4"
var_dump($dbh->lastInsertId());
// Nog drie records toevoegen: user_id 5, 6 en 7
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Karen'), ('Kristel'), ('Kathleen')
");
// Je zou user_id == 7 verwachten: string(1) "5"
var_dump($dbh->lastInsertId());
?>
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
$dsn = 'mysql:host=localhost;dbname=test';
$username = 'root';
$password = '';
$dbh = new \PDO($dsn, $username, $password);
$dbh->query("
CREATE TABLE IF NOT EXISTS users (
user_id SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
PRIMARY KEY pk_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci
");
// Drie records toevoegen: user_id 1, 2 en 3
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Jan'), ('Piet'), ('Joris')
");
// Je zou user_id == 3 verwachten, maar dit is: string(1) "1"
var_dump($dbh->lastInsertId());
// Record 2 bijwerken
$dbh->query("
UPDATE users
SET first_name = 'Kees'
WHERE user_id = 2
");
// We hebben niets toegevoegd: string(1) "0"
var_dump($dbh->lastInsertId());
// Nog een record toevoegen: user_id wordt 4
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Corneel')
");
// Nu wel juist: string(1) "4"
var_dump($dbh->lastInsertId());
// Nog drie records toevoegen: user_id 5, 6 en 7
$dbh->query("
INSERT INTO users (first_name)
VALUES ('Karen'), ('Kristel'), ('Kathleen')
");
// Je zou user_id == 7 verwachten: string(1) "5"
var_dump($dbh->lastInsertId());
?>
Bij de eerste INSERT met id 1, 2 en 3 is lastInsertId() 1; bij de derde INSERT met id 5, 6 en 7 is lastInsertId() 5. Het lijkt er dus op dat bij een INSERT van meerdere records de eerste id (1 en 5) wordt gebruikt. En dat is niet de hoogste id (3 en 7).
Gewijzigd op 23/09/2016 07:28:28 door Ward van der Put
Ward van der Put op 23/09/2016 06:25:50:
// Drie records toevoegen: user_id 1, 2 en 3
[...]
// Je zou user_id == 3 verwachten, maar dit is: string(1) "1"
[...]
// Je zou user_id == 3 verwachten, maar dit is: string(1) "1"
Interessant. Waarom zou je dat verwachten? ;-)
Als je het insert_id opvraagt, doe je dat met een reden. Die reden is niet omdat je het id van het volgende record wilt berekenen (dat wordt immers gegenereerd door de database) maar waarschijnlijk omdat je de inserts wilt nabewerken. En in dat geval heb je meer aan het id van het eerste ingevoegde record dan aan dat van het laatste.
In software engineering zijn drie dingen moeilijk: naamgeving en tellen. Dit is zo'n voorbeeld van naamgeving. Een functienaam als id_of_first_inserted_record_for_latest_query() is ook niet de meest handige.
Quote:
Het lijkt er dus op dat bij een INSERT van meerdere records de eerste id (1 en 5) wordt gebruikt.
Technisch gezien wordt het auto_increment-id gebruikt dat de tabel had vlak voor het eerste record werd ingevoegd. (En ja, ik heb ook de sourcecode van MySQL erbij gehaald. ;-) )
Gewijzigd op 23/09/2016 08:55:57 door Willem vp
Dan is deze frisse blik onder de motorkap dus wat er in de documentatie ontbreekt:
Willem vp op 23/09/2016 08:50:28:
En in dat geval heb je meer aan het id van het eerste ingevoegde record dan aan dat van het laatste.
[…]
Technisch gezien wordt het auto_increment-id gebruikt dat de tabel had vlak voor het eerste record werd ingevoegd.
[…]
Technisch gezien wordt het auto_increment-id gebruikt dat de tabel had vlak voor het eerste record werd ingevoegd.