2016-04-16 8 views
0

Betrachten Sie die folgenden drei Abfragen.MySQL INSERT zeigt mehr betroffene Zeilen als betroffen

Der erste kann nur eine einzelne Zeile zurückgeben, da bids_buy.id der Primärschlüssel ist.

Die zweite zeigt einen vorhandenen Datensatz in entities_has_documents für Primärschlüssel 3099541982-2536988132, und der dritte wird nicht aufgrund der vorhandenen Datensatz ausgeführt.

Der vierte wird wie erwartet ausgeführt, zeigt jedoch zwei betroffene Zeilen.

Warum werden zwei betroffene Zeilen angezeigt und nicht nur eine, die dem Primärschlüssel 3099541982-2536988132 zugeordnet ist?

mysql> SELECT bb.bids_sell_id, 2536988132,"pub_bids", NOW(),506836355 FROM bids_buy bb WHERE bb.id=2453409798; 
+--------------+------------+----------+---------------------+-----------+ 
| bids_sell_id | 2536988132 | pub_bids | NOW()    | 506836355 | 
+--------------+------------+----------+---------------------+-----------+ 
| 3099541982 | 2536988132 | pub_bids | 2016-04-16 08:19:13 | 506836355 | 
+--------------+------------+----------+---------------------+-----------+ 
1 row in set (0.00 sec) 

mysql> SELECT * FROM entities_has_documents; 
+-------------+--------------+----------+---------------------+--------------+-----------+------------+-----------+-------------+ 
| entities_id | documents_id | type  | date_added   | date_removed | added_by | removed_by | purged_by | date_purged | 
+-------------+--------------+----------+---------------------+--------------+-----------+------------+-----------+-------------+ 
| 2453409798 | 2536988132 | pub_bids | 2016-04-16 08:07:13 | NULL   | 506836355 |  NULL |  NULL | NULL  | 
| 3099541982 | 2536988132 | pub_bids | 2016-04-16 08:18:53 | NULL   | 506836355 |  NULL |  NULL | NULL  | 
+-------------+--------------+----------+---------------------+--------------+-----------+------------+-----------+-------------+ 
2 rows in set (0.00 sec) 

mysql> INSERT INTO entities_has_documents(entities_id,documents_id,type,date_added,added_by) 
    -> SELECT bb.bids_sell_id, 2536988132,"pub_bids", NOW(),506836355 FROM bids_buy bb WHERE bb.id=2453409798; 
ERROR 1062 (23000): Duplicate entry '3099541982-2536988132' for key 'PRIMARY' 

mysql> INSERT INTO entities_has_documents(entities_id,documents_id,type,date_added,added_by) 
    -> SELECT bb.bids_sell_id, 2536988132,"pub_bids", NOW(),506836355 FROM bids_buy bb WHERE bb.id=2453409798 
    -> ON DUPLICATE KEY UPDATE type="pub_bids", added_by=506836355, date_added=NOW(), removed_by=NULL, date_removed=NULL; 
Query OK, 2 rows affected (0.00 sec) 
Records: 1 Duplicates: 1 Warnings: 0 

mysql> EXPLAIN bids_buy; 
+--------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+--------------+------------------+------+-----+---------+-------+ 
| id   | int(10) unsigned | NO | PRI | NULL |  | 
| bids_sell_id | int(10) unsigned | NO | MUL | NULL |  | 
| stage_buy_id | int(10) unsigned | NO | MUL | NULL |  | 
+--------------+------------------+------+-----+---------+-------+ 
3 rows in set (0.01 sec) 

mysql> EXPLAIN entities_has_documents; 
+--------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+--------------+------------------+------+-----+---------+-------+ 
| entities_id | int(10) unsigned | NO | PRI | NULL |  | 
| documents_id | int(10) unsigned | NO | PRI | NULL |  | 
| type   | varchar(16)  | NO | MUL | NULL |  | 
| date_added | datetime   | NO |  | NULL |  | 
| date_removed | datetime   | YES |  | NULL |  | 
| added_by  | int(10) unsigned | NO | MUL | NULL |  | 
| removed_by | int(10) unsigned | YES | MUL | NULL |  | 
| purged_by | int(10) unsigned | YES | MUL | NULL |  | 
| date_purged | datetime   | YES |  | NULL |  | 
+--------------+------------------+------+-----+---------+-------+ 
9 rows in set (0.01 sec) 

mysql> 

EDIT

Per http://php.net/manual/en/pdostatement.rowcount.php

Wenn die letzte von der zugeordneten PDOStatement ausgeführten SQL-Anweisung war eine SELECT-Anweisung, einige Datenbanken können die Anzahl der Zeilen zurückkehren, indem die zurück Erklärung. Dieses Verhalten ist jedoch nicht für alle Datenbanken garantiert und sollte nicht für tragbare Anwendungen verwendet werden.

So sehe ich nur die Nummer oder Zeilen aus meiner SELECT-Anweisung zurückgegeben, und nicht die Anzahl oder Zeilen von meiner INSERT betroffen? Warum würde MySQL so etwas tun?

EDIT DONE

Antwort

1

ich denke, es wegen ON DUPLICATE KEY UPDATE Modifikator ist als die MYSQL Reference Manual 5.5 sowie MySQL Reference Manual 5.7 sagt

Wenn Sie ON DUPLICATE KEY UPDATE angeben, und eine Zeile eingefügt, die dazu führen würde, Ein doppelter Wert in einem UNIQUE-Index oder PRIMARY KEY, ein UPDATE der alten Zeile wird ausgeführt. Der Wert für betroffene Zeilen pro Zeile ist 1, wenn die Zeile als neue Zeile eingefügt wird, 2, wenn eine vorhandene Zeile aktualisiert wird, und 0, wenn für eine vorhandene Zeile die aktuellen Werte festgelegt sind. Wenn Sie beim Verbinden mit mysqld das CLIENT_FOUND_ROWS-Flag für mysql_real_connect() angeben, ist der Wert für betroffene Zeilen 1 (nicht 0), wenn eine vorhandene Zeile auf ihre aktuellen Werte gesetzt ist. ".

In Ihrem Fall hatten Sie bereits eine Zeile mit Primärschlüsselwert 3099541982-2536988132. Daher teilt Ihnen MySQL mit, dass Sie versuchen, eine Zeile mit doppeltem primären oder eindeutigen Schlüssel einzufügen, indem Sie 2 betroffene Zeilen angeben. Wie das Handbuch auch sagen, dass ON DUPLICATE KEY UPDATE führt zu der Sequenz INSERT als UPDATE Update-Befehl im Falle eines doppelten Schlüssel, während es nur die INSERT Befehl ausgeführt, falls der Schlüssel nicht vorhanden ist.

Ich hoffe, das hilft.

UPDATE

Auch diese link sehen.

+0

Wow, Sie sagen also, dass "betroffene Zeilen" nichts mit der Anzahl der betroffenen Zeilen zu tun hat?Ich stimme Ihnen völlig zu, dass die Dokumentation dies zu sagen scheint, aber niemals erwartet hat. – user1032531

+0

Ja, Sie haben recht, es ist mysql Semantik, um den Benutzer wissen zu lassen, welche Art von Befehl Sie verwenden und was es in Bezug auf die Anzahl der Operationen usw. führen wird. Sie können einfach versuchen, truncate Befehl löscht alle Zeilen in der Tabelle aber es gibt die Anzahl der betroffenen Zeilen als 0 zurück, weil truncate der DDL-Befehl ist und zu der Folge von DROP und CREATE TABLE führt. Daher ist die Anzahl der betroffenen Zeilen 0 gemäß der Semantik des DDL-Befehls. – geeksal

+0

Danke Geeksal, große Antwort, und auf jeden Fall etwas gelernt heute. – user1032531

Verwandte Themen