[MySQL] SELECT <PK IS NULL> na INSERT

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 22-09 10:29

Priet

To boldly do what no one has..

Topicstarter
Ik ben de weg kwijt. Ik probeer iets te doen in MySQL wat andere resultaten geeft dan ik zou verwachten, en ik snap niet waarom

Gegeven de volgende tabel:
SQL:
1
2
3
4
CREATE TABLE `test` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 255 ) NOT NULL
) ENGINE = MYISAM ;


En de volgende query om uit te voeren (het zijn twee queries die in één keer worden uitgevoerd):
SQL:
1
2
INSERT INTO `test` (`name`) VALUES ('dummy'); 
SELECT `id`, `name` FROM test WHERE `id` IS NULL;


Geeft dit als resultaat:
code:
1
2
3
4
5
6
7
8
9
mysql> INSERT INTO `test` (`name`) VALUES ('dummy'); SELECT `id`, `name` FROM test WHERE `id` IS NULL;
Query OK, 1 row affected (0.00 sec)

+----+-------+
| id | name  |
+----+-------+
|  1 | dummy |
+----+-------+
1 row in set (0.00 sec)


Hoe kan daar nu een rij uitkomen met id=1 (die door de eerste query is toegevoegd)? In de query geeft ik toch op id IS NULL? Als ik daarna de SELECT query nog een keer uitvoer komt er geen resultaat:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> INSERT INTO `test` (`name`) VALUES ('dummy');
Query OK, 1 row affected (0.03 sec)

mysql> SELECT `id`, `name` FROM test WHERE `id` IS NULL;
+----+-------+
| id | name  |
+----+-------+
|  2 | dummy |
+----+-------+
1 row in set (0.00 sec)

mysql> SELECT `id`, `name` FROM test WHERE `id` IS NULL;
Empty set (0.00 sec)


Een selectie op name geeft daarentegen geen resultaten (zoals ik zou verwachten):

code:
1
2
3
4
mysql> INSERT INTO `test` (`name`) VALUES ('dummy'); SELECT `id`, `name` FROM test WHERE `name` IS NULL;
Query OK, 1 row affected (0.00 sec)

Empty set (0.01 sec)


Waarom geeft MySQL de zojuist toegevoegde rij terug als ik een record opvraag waarvan de PK gelijk is aan NULL :?

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • H3llrais3r
  • Registratie: Mei 2005
  • Laatst online: 22-09 16:26
Beste

kijk even naar je eerste create regel:

`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,

Dit verteld, dat Kolom id een INTEGER waarde is *unsigned laat ik even liggen*
NOT NULL wil zeggen laat geen NULL toe in kolom
AUTO_INCREMENT, bij toevoeging verhoog kolom regel counter
PRIMARY KEY, zorg dat er geen meerdere regels kunnen bestaan met dezelfde ID's

de waarde wordt automatisch opgehoogd.
ID_counter in het begin Creatie van de tabel is 0;

deze kan je ook resetten (google is your friend)

omdat ID een PK is, kan deze tevents nooit NULL zijn. Vandaar selectie op NULL = LEEG

mySql doet dus ID automatisch op 1 zetten :)
bij nieuwe instert met alleen name wordt id op 2 gezet

[ Voor 52% gewijzigd door H3llrais3r op 08-03-2011 13:31 ]


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
H3llrais3r schreef op dinsdag 08 maart 2011 @ 13:23:


mySql doet dus ID automatisch op 1 zetten :)
Ja, maar de vraag van TS is juist waarom bij een WHERE van ID IS NULL er toch een record getoond wordt met ID = 1.

Ik ken MySQL niet heel goed, maar het zal waarschijnlijk te maken hebben met een transactie die nog niet gecommit is icm een isolation level dat dirty reads toestaat? Iemand met meer MySQL kennis die dit kan bevestigen?

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 21:04
Lijk me dat de ID wordt gezet, nadat de record is toegevoegd.

Dus:
  1. Voeg nieuwe record toe met naam
  2. Zet ID met waarde
  3. Bewaar de record
Omdat je de query direct na het inserten doet, is het mogelijk dat het systeem nog niet stap 2 heeft gedaan en dus een foutieve record in het geheugen heeft. Met enige tijd ertussen (1 ms.) kan het systeem wél verder met de stappen en heb je dus de goede situatie.

Maar waarom doe je die SELECT. :? Gezien de restricties in je tabel zou deze in principe geen resultaten terug moeten geven. En lijkt me dus overbodig.

Maar geen idee waarom MySQL zo reageert. Lijkt me dat het zo opgezet is, dus is er niets te vinden in de documentatie van MySQL (over de AUTO_INCREMENT).

let the past be the past.


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
De twee queries die je uitvoert in een keer geven maar 1 resultaat. Je ziet dus het resultaat van je insert, niet het resultaat van je select.

Dat zou mijn gok zijn.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Hmm, je hebt te maken met http://dev.mysql.com/doc/...is-null-optimization.html
If a WHERE clause includes a col_name IS NULL condition for a column that is declared as NOT NULL, that expression is optimized away.
Tja..

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 22-09 10:29

Priet

To boldly do what no one has..

Topicstarter
P_de_B schreef op dinsdag 08 maart 2011 @ 13:28:
(...) maar het zal waarschijnlijk te maken hebben met een transactie die nog niet gecommit is icm een isolation level dat dirty reads toestaat?
SPee schreef op dinsdag 08 maart 2011 @ 14:10:
Omdat je de query direct na het inserten doet, is het mogelijk dat het systeem nog niet stap 2 heeft gedaan en dus een foutieve record in het geheugen heeft.
Het lijkt er inderdaad op dat MySQL tijdelijk de nieuwe record met PK=NULL (id=NULL) wegschrijft. Op het moment dat je PK IS NULL opvraagt krijg je dus deze (tijdelijke?) record terug. Tussendoor een COMMIT geven geeft geen ander resultaat.
SPee schreef op dinsdag 08 maart 2011 @ 14:10:
Met enige tijd ertussen (1 ms.) kan het systeem wél verder met de stappen en heb je dus de goede situatie.
Met tijd heeft het niks te maken. De eerstvolgende query binnen dezelfde connectie op dezelfde tabel geeft altijd het zojuist ingevoegde record terug. Ook al wacht je een minuut.
Grijze Vos schreef op dinsdag 08 maart 2011 @ 14:38:
De twee queries die je uitvoert in een keer geven maar 1 resultaat. Je ziet dus het resultaat van je insert, niet het resultaat van je select.

Dat zou mijn gok zijn.
Leuke gok ;) Maar onjuist. Ook als je het op de MySQL CLI niet tegelijk maar na elkaar (zie ook tweede voorbeeld uit TS) uitvoert krijg je dezelfde response. Blijkbaar omdat het binnen dezelfde connectie wordt uitgevoerd.

Zodra je de PK tijdens de INSERT wél opgeeft (en de PK dus nooit NULL is) geeft de volgende SELECT geen resultaat (zoals verwacht).

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Nee, dan zou hij 2 results krijgen bij zijn tweede query.
Kijk maar naar de queries die hij invoert. De eerste insert + select geeft precies dezelfde output als de tweede insert. Gewoon een standaard "de insert is gelukt, dit is je inserted row". De select query wordt daar gewoon genegeerd.


Of ik kijk scheef. ;)

[ Voor 3% gewijzigd door Grijze Vos op 08-03-2011 15:21 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

Verwijderd

Is MySQL niet zo in te stellen dat ie op dat moment een harde error geeft? Het is immers een foutieve query, vragen om NULL op een niet NULLable kolom.

Het lijkt me op zich logisch dat een ongeldige query ook een vrij willekeurig resultaat geeft. De tekortkoming aan MySQL is dat deze vaak toch gaat proberen er iets mee te doen en de gebruiker niet op de hoogte stelt van de fout. Maar met settings is dit gedrag wel bij te schaven.

Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Ja, ik had "Als ik daarna de SELECT query nog een keer uitvoer komt er geen resultaat:" even gemist.

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 22-09 10:29

Priet

To boldly do what no one has..

Topicstarter
Verwijderd schreef op dinsdag 08 maart 2011 @ 15:21:
Is MySQL niet zo in te stellen dat ie op dat moment een harde error geeft? Het is immers een foutieve query, vragen om NULL op een niet NULLable kolom.

Het lijkt me op zich logisch dat een ongeldige query ook een vrij willekeurig resultaat geeft. De tekortkoming aan MySQL is dat deze vaak toch gaat proberen er iets mee te doen en de gebruiker niet op de hoogte stelt van de fout. Maar met settings is dit gedrag wel bij te schaven.
Het lijkt me geen foutieve query, eerder onlogisch. Een IS NULL query op een kolom die nooit NULL kan zijn zou daarom nooit resultaten kunnen geven.

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Priet schreef op dinsdag 08 maart 2011 @ 15:28:
[...]

Het lijkt me geen foutieve query, eerder onlogisch. Een IS NULL query op een kolom die nooit NULL kan zijn zou daarom nooit resultaten kunnen geven.
Inderdaad, daarom snap ik de optimalisatie die MySQL by design doet dus ook niet. "Je query kan nooit resultaten opleveren dus ik geef je gewoon alle records" :?

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 22-09 10:29

Priet

To boldly do what no one has..

Topicstarter
'alle' records is overdreven, het is ook niet willekeurig. Het is echt degene die zojuist is toegevoegd.

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Priet schreef op dinsdag 08 maart 2011 @ 16:23:
'alle' records is overdreven, het is ook niet willekeurig. Het is echt degene die zojuist is toegevoegd.
Ja, dat is bij jou het geval, maar als ik de documentatie van MySQL lees haalt hij het hele WHERE statement er af.

Het is ook geen verklaring voor het gedrag dat jij ziet(dat dacht ik eerst), dat moet denk ik toch in een nog niet gecommitte transactie oid zitten.

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
P_de_B schreef op dinsdag 08 maart 2011 @ 16:34:
Ja, dat is bij jou het geval, maar als ik de documentatie van MySQL lees haalt hij het hele WHERE statement er af.
Nee, dat staat er niet: er staat dat that expression is optimized away - dat lees ik als 'wordt vervangen door een constante FALSE', niet als 'wordt geheel weggehaald'.

Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022

Acties:
  • 0 Henk 'm!

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 21-09 18:54
Ben ik de enige (Heb niet bijzonder véél verstand van MySQL) maar is dit niet belachelijk? (Of in ieder geval niet consistent).

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Ja, het is belachelijk, en is er blijkbaar ooit ingefietst omdat iemand de feature bij Access leuk vond.

Maar goed, ik kan me zelf niet voorstellen dat ik in de praktijk hier per ongeluk last van heb, dus verbaas me eigenlijk ook wel hoe ts het ontdekt heeft. :+
ValHallASW schreef op dinsdag 08 maart 2011 @ 20:04:
[...]

Nee, dat staat er niet: er staat dat that expression is optimized away - dat lees ik als 'wordt vervangen door een constante FALSE', niet als 'wordt geheel weggehaald'.
Correct.

[ Voor 36% gewijzigd door Voutloos op 08-03-2011 20:43 ]

{signature}


Acties:
  • 0 Henk 'm!

  • Priet
  • Registratie: Januari 2001
  • Laatst online: 22-09 10:29

Priet

To boldly do what no one has..

Topicstarter
Verwijderd schreef op dinsdag 08 maart 2011 @ 20:20:
[...]

OMG, it's not a bug, it's a feature :D
ARGH daar was ik al bang voor 8)7

Inderdaad een belachelijke feature als je het mij vraagt |:(
Voutloos schreef op dinsdag 08 maart 2011 @ 20:42:Maar goed, ik kan me zelf niet voorstellen dat ik in de praktijk hier per ongeluk last van heb, dus verbaas me eigenlijk ook wel hoe ts het ontdekt heeft. :+
Het is een gave :P Het stukje is onderdeel van een groter framework wat automatisch een aantal checks uitvoert. Nu was dit onderdeeltje nog net niet helemaal goed geoptimaliseerd zodat er loze queries zoals <PK> IS NULL uit kwamen rollen. Nu had ik dat direct op kunnen lossen maar ik wilde toch weten of dit gedrag door een ander onderdeel van het framework werd veroorzaakt of door MySQL zelf. Ik kwam al snel op het laatste, maar de reden was mij nog volstrekt onduidelijk.

Eigenlijk is het waarom nog steeds niet duidelijk, maar ik snap in ieder geval wie hier verantwoordelijk voor is :+

"If you see a light at the end of a wormhole, it's probably a photon torpedo!"


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Even voor de duidelijkheid, je kunt het uitzetten. Ik kan me geen normale situatie bedenken waarbij ik zou willen zoeken op een NULL auto_increment veld, dus last zul je er in het algemeen niet van hebben.

Waarom? Omdat dit blijkbaar standaard gedrag is voor Access zo hou je de boel een beetje compatable denk.

Ik vond het verhaal over performance wel vermakelijk :).
Pagina: 1