Heim  >  Artikel  >  Datenbank  >  Der MySQL-Prozedurparameter ist eine NULL-Problemanalyse

Der MySQL-Prozedurparameter ist eine NULL-Problemanalyse

高洛峰
高洛峰Original
2016-12-02 14:48:261577Durchsuche

Ich habe kürzlich eine interessante Sache entdeckt, wenn das Schreiben einer MySQL-Prozedur beim Übergeben von Parametern auf eine einzigartige Art und Weise mit einigen „illegalen“ Parametern umgeht. Wenn beispielsweise ein ursprünglich als int definierter Parameter als null
übergeben wird, wird die MySQL-Prozedur normal ausgeführt.
Bibliothekstabellenstruktur:
Datenbank db5 erstellen;

db5 verwenden;

Tabelle löschen, falls vorhanden t;
Tabelle erstellen t(
id int Primary Key Auto_Increment ,
value int
);

create table t2(
id int Primary key auto_increment,
value float
);
Prozedur erstellen:
delimiter //
CREATE PROCEDURE p14 (IN Parameter1 INT)
BEGIN
DECLARE Variable1 INT;
SET Variable1 = Parameter1 + 1;
INSERT INTO t(value) VALUES (Variable1);
ENDE;
//
Trennzeichen ;

Ergebnis ausführen:


mysql> call p14(5);
Abfrage OK, 1 Zeile betroffen (0,02 sec)

mysql> select * from t;
+----+-------+
+----+- ------+
|. 6 |
+----+-------+
1 Zeile im Satz (0,00 Sek.)

mysql> ; call p14(null);
Abfrage OK, 1 Zeile betroffen (0,04 Sek.)

mysql>select * from t;
+----+------+
|. id |.
+----+------+
|. ------+
2 Zeilen im Satz (0,00 Sek.)


Haben Sie bemerkt, dass, wenn der Parameter Parameter1 gleich 5 übergeben wird, 6 in die Tabelle und die Daten eingefügt wird? ist normal.
Wenn der Parameter Parameter1 als Null übergeben wird, wird NULL in die Tabelle eingefügt. Warum ist das so?

Zu diesem Punkt können Sie sich die Anweisung ansehen, die Variablen deklariert. Das Dokument gibt folgende Erklärung: Die Deklarationsanweisung wird zum Deklarieren lokaler Variablen verwendet. Um einen Standardwert für eine Variable bereitzustellen, fügen Sie eine DEFAULT-Klausel ein. Der Wert kann als Ausdruck angegeben werden und muss keine Konstante sein. Wenn keine DEFAULT-Klausel vorhanden ist, ist der Anfangswert NULL.

Oben gibt es eine neue Frage: NULL=NULL+1? Haha, das ist ein bisschen interessant. Was ist die vernünftige Erklärung für SET variable1 = parameter1 + 1?

Dies ist die Erklärung von Lehrer Wang (die zweite ist sehr klassisch~~~):
1 null+1=null
Weil null sich wie ein „Zeiger“ verhält, d. h. Es zeigt auf „0 Adressinhalt“. Wenn dieser Inhalt „null“ ist, wird er als null angezeigt. Deshalb ist auch die Angabe von INT leer. Wenn der „Inhalt“ jedoch einen Wert hat, ist er nicht leer. Bei MYSQL ist er eine „Zufallszahl“ oder 0; der Wert ist fest
2 Wenn A=B+1, ist A nur NULL, wenn B SET A=B+1 ist. Kann es als SET (B+1) verstanden werden, A wurde im „aktuellen“ ersetzt Es spielt keine Rolle, wer A ist, das Wichtigste ist B+1;
Diese Idee wurde nicht überprüft, hauptsächlich weil SET nicht getrennt werden kann und die Dokumentation von mysql5 diese Aussage unterstützt, aber die englische Version verwendet „Ersatz“. anstelle des chinesischen „set“-Ausdrucks fühlt sich die Bedeutung näher an! (SET)

Eine neue Frage: Kann es erfolgreich ausgeführt werden, wenn A=1/B und B=0?

mysql>

Trennzeichen //
CREATE PROCEDURE p15 (IN Parameter1 INT)
BEGIN
declare variable2 float(5,3);
SET variable2 = 1/ Parameter1;
INSERT INTO t2(value) VALUES (variable2);
END;
//
delimiter;

Ausführungsergebnis:

mysql> call p15(0);
Abfrage OK, 1 Zeile betroffen (0,03 Sek.)

mysql> select * from t2;
+----+--------+
|. id |.
+----+------+
|
1 Zeile im Satz (0,00 Sek.)

mysql> Aufruf p15(1);
Abfrage OK, 1 Zeile betroffen (0,03 Sek.)

mysql> select * from t2 ;
+----+------+
| |.
|. 1 |

Haben Sie es bemerkt? Das klappt auch erfolgreich. Tatsächlich kann dieses Problem in den Parameterdetails des SQL-Servermodus von MySQL gefunden werden.
Der MySQL-Server kann in verschiedenen SQL-Modi betrieben werden und verschiedene Modi können auf verschiedene Clients angewendet werden. Auf diese Weise kann jede Anwendung den Betriebsmodus des Servers an ihre eigenen Bedürfnisse anpassen.
Das Schema definiert, welche SQL-Syntax MySQL unterstützen soll und welche Art von Datenvalidierungsprüfungen durchgeführt werden sollen. Dies erleichtert die Verwendung von MySQL in verschiedenen Umgebungen und mit anderen Datenbankservern.
Sie können den Standard-SQL-Modus festlegen, indem Sie mysqld mit der Option --sql-mode="modes" starten. Dieser Wert kann auch leer gelassen werden (--sql-mode = „“), wenn Sie ihn zurücksetzen möchten.
Sie können auch die Anweisung SET [SESSION|GLOBAL] sql_mode='modes' verwenden, um die Variable sql_mode festzulegen, um den SQL-Modus nach dem Start zu ändern. Das Setzen einer GLOBAL-Variable erfordert die SUPER-Berechtigung und wirkt sich ab diesem Zeitpunkt auf den Betrieb aller verbundenen Clients aus. Das Setzen der SESSION-Variable wirkt sich nur auf den aktuellen Client aus. Jeder Client kann seinen Sitzungs-sql_mode-Wert jederzeit ändern.
Modesis ist eine Reihe verschiedener Modi, die durch Kommas („,“) getrennt sind. Sie können den aktuellen Modus mit der Anweisung SELECT @@sql_mode abfragen. Der Standardwert ist leer (es ist kein Modus festgelegt).
STRICT_TRANS_TABLES
Aktivieren Sie den strikten Modus für alle Speicher-Engines. Unzulässige Datenwerte werden abgelehnt. Detaillierte Anweisungen folgen.
· STRICT_TRANS_TABLES
Aktiviert den strikten Modus für transaktionale Speicher-Engines und möglicherweise für nicht-transaktionale Speicher-Engines. Detaillierte Anweisungen folgen.
Der strenge Modus steuert, wie MySQL mit illegalen oder fehlenden Eingabewerten umgeht. Es gibt mehrere Gründe, warum ein Wert illegal sein kann. Beispielsweise ist der Datentyp falsch, passt nicht in die Spalte oder liegt außerhalb des gültigen Bereichs. Wenn eine neu eingefügte Zeile keinen Wert für eine Spalte enthält, die nicht explizit eine DEFAULT-Klausel definiert, geht der Wert verloren.
Wenn bei Transaktionstabellen der Modus STRICT_ALL_TABLES oder STRICT_TRANS_TABLES aktiviert ist, tritt ein Fehler auf, wenn die Anweisung ungültige oder fehlende Werte enthält. Die Aussage wird aufgegeben und gerollt.
Bei nicht-transaktionalen Tabellen verhalten sich beide Modi gleich, wenn in Zeile 1 einer Einfügung oder Aktualisierung ein ungültiger Wert auftritt. Die Anweisung wird verworfen und die Tabelle bleibt unverändert. Wenn eine Anweisung mehrere Zeilen einfügt oder ändert und der fehlerhafte Wert in der zweiten oder späteren Zeile auftritt, hängt das Ergebnis davon ab, welche strikte Option aktiviert ist:
ERROR_FOR_DIVISION_BY_ZERO
Im strikten Modus, während INSERT oder UPDATE, wenn Null Division ( oder MOD(X, 0)) tritt ein Fehler auf (andernfalls eine Warnung). Wenn der Modus nicht angegeben ist, gibt MySQL bei der Division durch Null NULL zurück. Bei Verwendung in INSERT IGNORE oder UPDATE IGNORE generiert MySQL eine Division-durch-Null-Warnung, aber das Ergebnis der Operation ist NULL.
Es gibt andere Parameter, Leser können sich auf die MySQL-Dokumentation beziehen.

Wenn wir den Parameter ERROR_FOR_DIVISION_BY_ZERO zu sql_mode hinzufügen, starten Sie MySQL neu
mysql> show variables like 'sql_mode';
+--------------+ -- ------------------------------------------------ -- ----------
----------+
|Variablenname | 🎜>                                                                                  ----------------- -- --------------------+
|. STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_
USER,NO_ENGINE_SUBSTITUTION |
+---- - --------+-------------------------- - ---------
---------------------- -- ---+
1 Zeile im Satz (0,00 Sek.)

mysql>+------+
| 🎜> +------+
|. NULL |
+------+
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Wir sehen 1 Warnung, schauen wir uns diese Warnung an:
mysql>
+-------+------+------------- -- +
|. Nachricht |
+------+--------------+
|. Fehler |. 1365 |. Division durch 0 |
+------+--------------+
1 Zeile in set (0.00 sec)

mysql> exit
Bye
Wenn wir den Parameter ERROR_FOR_DIVISION_BY_ZERO im sql_mode entfernen, starten Sie mysql neu und versuchen Sie:

C:Documents and SettingsAdministrator>net stop mysql
MySQL-Dienst wird gestoppt.
MySQL-Dienst wurde erfolgreich gestoppt.


C:Documents and SettingsAdministrator>net start mysql

Der MySQL-Dienst wurde erfolgreich gestartet.


mysql> select 1/0;
+------+
| 1/0 |
+------++------+
1 Zeile im Satz (0,00 Sek.)

mysql> Warnungen anzeigen;
Leerer Satz (0,02 Sek.)
Warnungen dabei Zeit Der Inhalt ist leer.
An dieser Stelle wissen die Leser auch warum. Wenn Sie Zeit haben, probieren Sie andere Datenbanken aus und prüfen Sie, ob dies der Fall ist

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:MySQL-DatenformatNächster Artikel:MySQL-Datenformat