MySQL-Datentypen – offizielle Dokumente – Studiennotizen – numerische Werte, Datum und Uhrzeit, Zeichenfolgen, JSON

MySQL-Datentypen – offizielle Dokumente – Studiennotizen

Inhaltsverzeichnis

MySQL unterstützt mehrere Arten von SQL- Datentypen: numerische Typen, Datums- und Uhrzeittypen, Zeichenfolgentypen (Zeichen und Byte), räumliche Typen und JSONDatentypen. Dieses Kapitel bietet einen Überblick und eine detailliertere Beschreibung der Typeigenschaften in jeder Kategorie sowie eine Zusammenfassung der Speicheranforderungen für Datentypen.

Für Datentypbeschreibungen gelten die folgenden Konventionen:

  • Bei ganzzahligen Typen Mstellt * * die maximale Anzeigebreite dar. Bei Gleitkomma- und Festkommatypen Mist ** die Gesamtzahl der Bits, die gespeichert werden können (Genauigkeit). Bei String-Typen Mist * die maximale Länge. MDer maximal zulässige Wert von * hängt vom Datentyp ab.

  • * D*Gilt für Gleitkomma- und Festkommatypen und gibt die Anzahl der Nachkommastellen (Anzahl der Dezimalstellen) an. Der maximal mögliche Wert beträgt 30, sollte jedoch nicht größer als M-2 sein.

  • * fsp* Gilt für TIME, DATETIMEund TIMESTAMPgibt die Genauigkeit von Sekundenbruchteilen ein, d. h. die Anzahl der Sekundenbruchteile nach dem Dezimalpunkt. Der * fsp*-Wert muss, sofern angegeben, im Bereich von 0 bis 6 liegen. Ein Wert von 0 bedeutet keinen Dezimalteil. Wenn es weggelassen wird, ist die Standardgenauigkeit 0. (Dies unterscheidet sich aus Kompatibilitätsgründen mit früheren MySQL-Versionen vom Standard-SQL-Standardwert 6.)

  • Eckige Klammern ( [und ]) stellen optionale Teile der Typdefinition dar.

1. Numerischer Datentyp

1.1 Syntax numerischer Datentypen

1.2 Integer-Typen (exakte Werte) – INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT

1.3 Festkommatypen (genaue Werte) – DEZIMAL, NUMERISCH

1.4 Gleitkommatypen (ungefähre Werte) – FLOAT, DOUBLE

1,5-Bit-Werttyp – BIT

1.6 Numerische Typattribute

1.7 Handhabung außerhalb des zulässigen Bereichs und Überlauf

MySQL unterstützt alle standardmäßigen numerischen SQL-Datentypen.
Zu diesen Typen gehören exakte numerische Datentypen (INTEGER, SMALLINT, DECIMAL und NUMERIC) und ungefähre numerische Datentypen (FLOAT, REAL und DOUBLE PRECISION).
Das Schlüsselwort INT ist ein Synonym für INTEGER,
die Schlüsselwörter DEC und FIXED sind Synonyme für DECIMAL,
MySQL behandelt DOUBLE als Synonym für DOUBLE PRECISION (nicht standardmäßige Erweiterung),
MySQL behandelt REAL auch als Synonym für DOUBLE PRECISION (nicht standardmäßige Variante). ), es sei denn, der SQL-Modus REAL_AS_FLOAT ist aktiviert.

Der Datentyp BIT speichert „Bit“-Werte und unterstützt MyISAM-, InnoDB-, MEMORY- und NDB-Tabellen.

1.1 Syntax numerischer Datentypen

  • Stellt bei ganzzahligen Datentypen Mdie maximale Anzeigebreite dar. Die maximale Anzeigebreite beträgt 255. Die Anzeigebreite hat nichts mit dem Wertebereich zu tun, den ein Typ speichern kann. int(M)Beispiel: int(4)Gibt an, dass die maximale Anzeige 4 Ziffern beträgt, nämlich Einer, Zehner, Hunderter und Tausender.
  • Bei Gleitkomma- und Festkomma-Datentypen Mhandelt es sich um die Gesamtzahl der Ziffern, die gespeichert werden können (einschließlich des Dezimalteils). Das „Bit“ ist hier nicht dasselbe Konzept wie „Bit“. Das „Bit“ bezieht sich hier auf die Anzahl der Stellen in der Zahl, also die Einerstelle, Zehner usw.
    • 定点:decimal(M[,D]) 例子: decimal(1) 表示mysql只存储1位整数
    • 浮点: float(M[,D]) 例子: float(1) 表示mysql只存储1位整数

如果您为数字列指定 ZEROFILL,MySQL 会自动将 UNSIGNED 属性添加到该列。

数值数据类型允许 UNSIGNED 属性也允许 SIGNED。但是,这些数据类型默认是有符号的,所以 SIGNED 属性没有作用。

SERIAL DEFAULT VALUE 在整数列的定义中是 NOT NULL AUTO_INCREMENT UNIQUE 的别名。

警告
当您在类型为 UNSIGNED 的整数值之间使用减法时,除非启用 NO_UNSIGNED_SUBTRACTION 的 SQL 模式,否则结果是无符号的。

1.1.1 BIT[(M)]

位值类型。M表示每个值的位数,从 164。如果 M省略,则默认为 1

1.1.2 TINYINT[(M)] [UNSIGNED] [ZEROFILL]

一个非常小的整数,占1字节。有符号范围为 -2[^7] = -128 to 2[^7]-1 = 127。无符号范围是 0 to 2[^8]-1 = 255
M 表示最大显示宽度

1.1.3 BOOL, BOOLEAN

这些类型是 TINYINT(1) 的同义词。零值被认为是的。非零值被认为是的:

mysql> SELECT IF(0, 'true', 'false');
+------------------------+
| IF(0, 'true', 'false') |
+------------------------+
| false                  |
+------------------------+

mysql> SELECT IF(1, 'true', 'false');
+------------------------+
| IF(1, 'true', 'false') |
+------------------------+
| true                   |
+------------------------+

mysql> SELECT IF(2, 'true', 'false');
+------------------------+
| IF(2, 'true', 'false') |
+------------------------+
| true                   |
+------------------------+

但是,值TRUEFALSE只是 10 的别名,分别如下所示:

mysql> SELECT IF(0 = FALSE, 'true', 'false');
+--------------------------------+
| IF(0 = FALSE, 'true', 'false') |
+--------------------------------+
| true                           |
+--------------------------------+

mysql> SELECT IF(1 = TRUE, 'true', 'false');
+-------------------------------+
| IF(1 = TRUE, 'true', 'false') |
+-------------------------------+
| true                          |
+-------------------------------+

mysql> SELECT IF(2 = TRUE, 'true', 'false');
+-------------------------------+
| IF(2 = TRUE, 'true', 'false') |
+-------------------------------+
| false                         |
+-------------------------------+

mysql> SELECT IF(2 = FALSE, 'true', 'false');
+--------------------------------+
| IF(2 = FALSE, 'true', 'false') |
+--------------------------------+
| false                          |
+--------------------------------+

Die letzten beiden Anweisungen zeigen das Ergebnis von 2ungleich TRUEund FALSEweil 2weder gleich 1noch gleich ist 0.

1.1.4SMALLINT[(M)] [UNSIGNED] [ZEROFILL]

Eine kleine Ganzzahl, die 2Bytes belegt. Der vorzeichenbehaftete Bereich ist -2[^15] = -32768bis 2[^15]-1 = 32767. Der vorzeichenlose Bereich liegt 0bei 2[^16]-1 = 65535.

1.1.5MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]

Eine mittelgroße Ganzzahl in 3Bytes. Der vorzeichenbehaftete Bereich ist -2[^23] = -8388608bis 2[^23]-1 = 8388607. Der vorzeichenlose Bereich liegt 0bei 2[^24]-1 = 16777215.

1.1.6INT[(M)] [UNSIGNED] [ZEROFILL]

Eine Ganzzahl normaler Größe in 4Bytes. Der vorzeichenbehaftete Bereich ist -2[^31] = -2147483648bis 2[^31]-1 = 2147483647. Der vorzeichenlose Bereich liegt 0bei 2[^32]-1 = 4294967295.

1.1.7INTEGER[(M)] [UNSIGNED] [ZEROFILL]

Dieser Typ ist INTein Synonym für .

1.1.8BIGINT[(M)] [UNSIGNED] [ZEROFILL]

Eine große Ganzzahl, die 8Bytes belegt. Der vorzeichenbehaftete Bereich ist -2[^63] = -9223372036854775808bis 2[^63]-1 = 9223372036854775807. Der vorzeichenlose Bereich liegt 0bei 2[^64]-1 = 18446744073709551615.

SERIALJa, BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUEAlias.

Einige Dinge, die Sie bei Spalten BIGINTbeachten sollten :

  • Die gesamte Arithmetik erfolgt mit vorzeichenbehafteten BIGINTODER- Werten, daher sollten Sie keine vorzeichenlosen großen Ganzzahlen größer als (63 Bit) verwenden, außer bei Bitfunktionen! Wenn Sie dies tun, können einige der letzten Zahlen im Ergebnis aufgrund von Rundungsfehlern bei der Konvertierung des Werts in falsch seinDOUBLE9223372036854775807BIGINTDOUBLE

    MySQL kann BIGINTdie folgenden Situationen bewältigen:

    • Bei Verwendung von Ganzzahlen BIGINTzum Speichern großer vorzeichenloser Werte in Spalten.
    • BIGINTWenn Spalten für MIN(*col_name*) und MAX(*col_name*) verwendet werden
    • Bei Verwendung eines Operators , bei dem beide Operanden ganze Zahlen sind ( +, usw.).-*
  • BIGINTEs ist immer möglich , exakte ganzzahlige Werte zu speichern , indem man sie mithilfe einer Zeichenfolge einer Spalte zuordnet . In diesem Fall führt MySQL eine String-zu-Zahlen-Konvertierung durch, die keine dazwischenliegende doppelte Darstellung beinhaltet.

  • Die Operatoren , und verwenden Arithmetik -, wenn beide Operanden ganzzahlige Werte sind . Das bedeutet, dass Sie beim Multiplizieren zweier großer Ganzzahlen (oder des Ergebnisses einer Funktion, die eine Ganzzahl zurückgibt) möglicherweise unerwartete Ergebnisse erhalten, wenn das Ergebnis größer als ist .+*BIGINT9223372036854775807

1.1.9DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]

Eine komprimierte „exakte“ Festkommazahl.

  • * M* ist die Gesamtzahl der Ziffern (Genauigkeit), der Bereich liegt zwischen 1 und 65 und der Standardwert ist 10.
  • Dist die Anzahl der Stellen (Skala) rechts vom Dezimalpunkt. Der Wert liegt zwischen 0 und 30 und kann nicht größer seinM . Der Standardwert ist 0.
  • 小数点Vorzeichen und -(negative) Vorzeichen werden nicht mitgezählt M. Wenn ** D0 ist, hat der Wert keinen Dezimalpunkt oder Dezimalteil.

( DECIMALDie Länge von wörtlichem Text ist ebenfalls begrenzt; siehe Umgang mit Ausdrücken .)

Wenn angegeben UNSIGNED, sind negative Werte nicht zulässig.

DECIMALAlle Grundberechnungen mit den Spalten ( +, -, *, /) werden mit einer Genauigkeit von 65 Stellen durchgeführt.

1.1.10DEC[(M[,D])] [UNSIGNED] [ZEROFILL], NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL], FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]

Diese Typen sind DECIMALSynonyme für . FIXEDAus Gründen der Kompatibilität mit anderen Datenbanksystemen stehen Synonyme zur Verfügung.

1.1.11FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

Eine kleine Gleitkommazahl (einfache Genauigkeit). Zulässige Werte sind -3.402823466E+38to -1.175494351E-38, 0und 1.175494351E-38to 3.402823466E+38. Dies sind theoretische Grenzwerte, die auf IEEE-Standards basieren. Die tatsächliche Reichweite kann je nach Hardware oder Betriebssystem etwas geringer sein.

Mist die Gesamtzahl der Ziffern und Ddie Anzahl der Ziffern nach dem Dezimalpunkt. WennM und *D* weggelassen werden, wird der Wert innerhalb des von der Hardware zugelassenen Bereichs gespeichert. Gleitkommazahlen mit einfacher Genauigkeit haben eine Genauigkeit von etwa 7 Dezimalstellen.

FLOAT(M,D)Ist eine nicht standardmäßige MySQL-Erweiterung.

Wenn angegeben UNSIGNED, sind negative Werte nicht zulässig.

Die Verwendung FLOATkann zu unerwarteten Problemen führen, da alle Berechnungen in MySQL mit doppelter Genauigkeit durchgeführt werden. Siehe „Auflösen nicht übereinstimmender Zeilen“ .

1.1.12FLOAT(p) [UNSIGNED] [ZEROFILL]

一个浮点数。p 表示以位为单位的精度,但 MySQL 仅使用此值来确定是使用 FLOAT还是 DOUBLE用于生成的数据类型。如果*p是从 0 到 24,则数据类型变为FLOATM*或 *D*值。如果 *p*是从 25 到 53,则数据类型变为DOUBLEMD 值。结果列的范围与本节前面描述 的单精度FLOAT或双精度 DOUBLE 数据类型相同。

FLOAT(p) 为 ODBC 兼容性提供了语法。`

1.1.13 DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

一个正常大小(双精度)的浮点数。允许的值为 -1.7976931348623157E+308to -2.2250738585072014E-30802.2250738585072014E-308to 1.7976931348623157E+308。这些是基于 IEEE 标准的理论限制。根据您的硬件或操作系统,实际范围可能会稍小一些。

M是总位数,D是小数点后的位数。如果省略M 和*D*,则将值存储在硬件允许的范围内。双精度浮点数精确到大约 15 位小数。

DOUBLE(M,D) 是一个非标准的 MySQL 扩展。

如果指定 UNSIGNED,则不允许负值。

1.1.14 DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], REAL[(M,D)] [UNSIGNED] [ZEROFILL]

1.2 整数类型(精确值) - INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、BIGINT

MySQL unterstützt die SQL-Standard-Integer-Typen INTEGER(oder INT) und SMALLINT. Als Erweiterung des Standards unterstützt MySQL auch die Integer-Typen TINYINT, MEDIUMINTund BIGINT. Die folgende Tabelle zeigt den für jeden Integer-Typ erforderlichen Speicherplatz und Bereich.

Tabelle 1.1 Erforderlicher Speicher und Bereich der von MySQL unterstützten Ganzzahltypen

Typ Speicher (Byte) Mindestwert (mit Vorzeichen) Maximalwert (mit Vorzeichen) Mindestwert (ohne Vorzeichen) Maximalwert (ohne Vorzeichen)
TINYINT 1 -128 127 0 255
SMALLINT 2 -32768 32767 0 65535
MEDIUMINT 3 -8388608 8388607 0 16777215
INT 4 -2147483648 2147483647 0 4294967295
BIGINT 8 -2[^63] 2[^63]-1 0 2[^64]-1

1.3 Festkommatypen (genaue Werte) – DEZIMAL, NUMERISCH

DECIMALund NUMERIC-Typen speichern exakte numerische Datenwerte. Verwenden Sie diese Typen, wenn die Aufrechterhaltung einer präzisen Genauigkeit wichtig ist, beispielsweise bei Währungsdaten. In MySQL NUMERICist es als implementiert , daher gilt DECIMALFolgendes auch :DECIMALNUMERIC

MySQL DECIMALspeichert Werte im Binärformat (Hinweis: Anstatt numerische Zeichen in Zeichenfolgen zu speichern, weil ich zuerst dachte, es wären Zeichenfolgen), werden jeweils 9 numerische Zeichen segmentiert und in 4 Bytes gespeichert, und Ganzzahlen werden separat gespeichert , und der Dezimalteil wird ebenfalls nach jeweils 9 numerischen Zeichen segmentiert. Für den Teil, der nach der Segmentierung weniger als 9 Zeichen umfasst, werden die verbleibenden Ziffern nach dem Prinzip der minimalen Anzahl von Bytes gespeichert. Einzelheiten zur Speicherung finden Sie unter „Exakte Mathematik“ .

DECIMALGenauigkeit und Skalierung können (und werden in der Regel auch) in der Spaltendeklaration angegeben . Zum Beispiel:

salary DECIMAL(5,2)

In diesem Fall 5ist es die Genauigkeit und 2die Anzahl der Dezimalstellen. Die Präzision wird als die Anzahl der signifikanten Stellen ausgedrückt, in denen der Wert gespeichert wird, und die Skalierung wird als die Anzahl der Stellen ausgedrückt, die nach dem Dezimalpunkt gespeichert werden können.

Standard-SQL erfordert DECIMAL(5,2)die Fähigkeit, jeden Wert mit 5 Ziffern und 2 Dezimalstellen zu speichern, sodass salaryder Wertebereich, der in der Spalte gespeichert werden kann, von -999.99bis reicht 999.99.

In Standard-SQL DECIMAL(M)entspricht die Syntax DECIMAL(M,0). DECIMALIn ähnlicher Weise entspricht die Syntax der von DECIMAL(M,0), sodass die Implementierung den Wert von bestimmen kann M. MySQL unterstützt diese beiden unterschiedlichen Formen der DECIMALSyntax. MDer Standardwert ist 10.

Wenn die Dezimalzahl 0 ist, DECIMALenthält der Wert weder einen Dezimalpunkt noch einen Dezimalteil.

DECIMALDie maximale Anzahl an Ziffern beträgt 65, der tatsächliche Bereich einer bestimmten DECIMALSpalte kann jedoch durch die Genauigkeit oder Skalierung der angegebenen Spalte begrenzt sein. Wenn ein einer solchen Spalte zugewiesener Wert mehr als eine bestimmte Anzahl zulässiger Dezimalstellen aufweist, wird der Wert in diese Anzahl Dezimalstellen konvertiert. (Das genaue Verhalten ist betriebssystemspezifisch, aber normalerweise wird dadurch auf die Anzahl der zulässigen Bits gekürzt.)

1.4 Gleitkommatypen (ungefähre Werte) – FLOAT, DOUBLE

FLOATund DOUBLETypen stellen ungefähre numerische Datenwerte dar. MySQL verwendet vier Bytes für Werte mit einfacher Genauigkeit und acht Bytes für Werte mit doppelter Genauigkeit.

Für FLOAT, erlaubt der SQL-Standard, dass Schlüsselwörter in Klammern die Genauigkeit der folgenden Dezimalzahlen (jedoch nicht den Exponentenbereich) in Biteinheiten angeben (beachten Sie, dass sie sich von den Ziffern von Festkommazahlen unterscheidet, hier handelt es sich um Binärziffern). ist FLOAT(p). MySQL unterstützt auch diese optionale Genauigkeitsangabe, FLOAT(p)der Präzisionswert von wird jedoch nur zur Bestimmung der Speichergröße verwendet, und eine Genauigkeit von 0 bis 23 erzeugt eine 4-Byte- FLOATSpalte mit einfacher Genauigkeit. Genauigkeiten von 24 bis 53 erzeugen eine 8-Byte-Doppelspalte DOUBLE.

MySQL erlaubt die Verwendung einer nicht standardmäßigen Syntax: FLOAT(M,D)oder REAL(M,D)oder DOUBLE PRECISION(M,D). Hier bedeutet das, dass insgesamt bis zu Ziffern (M,D)gespeichert werden können , davon Nachkommastellen. Eine als definierte Spalte sieht beispielsweise so aus: . MySQL führt beim Speichern von Werten eine Rundung durch. Wenn sie also in die Spalte eingefügt werden, ist das ungefähre Ergebnis, dass die Ziffer nach der 4. Dezimalstelle gerundet wird und 0,00009 auf 0,00010 „gerundet“ wird.MD
FLOAT(7,4)-999.9999999.00009FLOAT(7,4)999.0001

Da Gleitkommawerte Näherungswerte sind und nicht als exakte Werte gespeichert werden, kann der Versuch, sie in Vergleichen als exakte Werte zu behandeln, zu Problemen führen. Sie sind auch von Plattform- oder Implementierungsabhängigkeiten betroffen. Weitere Informationen finden Sie unter „Probleme mit Gleitkommawerten“ .

Für maximale Portabilität sollte Code, der ungefähre numerische Datenwerte speichern muss, die Genauigkeit oder Anzahl der Ziffern verwenden FLOAToder nicht angeben.DOUBLE PRECISION

1,5- Bit-Werttyp - BIT

BITDer Datentyp wird zum Speichern von (binären) „Bit“-Werten verwendet. Ein BIT(M)Typ ermöglicht die Speicherung Mbinärer Ziffernwerte. MDer Bereich kann zwischen 1 und 64 liegen.

Um den Wert eines „Bits“ anzugeben, kann die Binärschreibweise verwendet werden b'value'. bGibt an, dass darauf eine in einfache Anführungszeichen gesetzte Binärzahl folgt und valueein Binärwert ist, der aus Nullen und Einsen geschrieben wird. Beispielsweise stellen b'111'und b'10000000'eine Dezimalzahl 7bzw. dar 128. Siehe „Stellenwertliteral“ .

Wenn einer Spalte ein MWert mit einer Länge von weniger als ** Bits zugewiesen wird BIT(M), wird der Wert links mit Nullen aufgefüllt. Wenn der Spalte beispielsweise b'101'der Wert von zugewiesen wird , wird die linke Seite mit ausreichend aufgefüllt, um die Ziffern auszugleichen , und in MySQL gespeichert, BIT(6)da 101nur drei Binärziffern vorhanden sind, was für die erwarteten Ziffern nicht ausreicht .606b'000101'

NDB-Cluster : Die maximale Gesamtgröße aller in einer bestimmten Tabelle NDBverwendeten Spalten darf 4096 Bit nicht überschreiten.BIT

1.6 Numerische Typattribute

1.6.1 int(M)

int(6) Die 6 in den Klammern stellt die maximale Anzahl von Ziffern dar, die „angezeigt“ werden können, aber es handelt sich um ein anderes Konzept als die „Anzahl der gespeicherten Bits“. Sie haben keine Beziehung und beeinflussen sich nicht gegenseitig.
Der Typ int belegt 4 Bytes, 32 Binärbits, der Maximalwert beträgt 2,1 Milliarden und die Anzahl der vollständigen Zahlen beträgt 10 Ziffern. int(6) bedeutet, dass die Anwendung maximal 6 Ziffern anzeigen soll. Diese „6 Ziffern“ beginnen von rechts nach links zu zählen und zählen bis zur 6. Ziffer, also Einer, Zehner, Hunderter, Tausender, Zehntausender und Zehner . Tausende Menschen.
Ob (6) unterstützt wird, hängt von der Verarbeitung der Anwendung ab. MySQL empfiehlt nur die Anzeige von maximal 6 Ziffern.
Beispiel: Wenn die Zahl „1234567“ im Feld von int(6) gespeichert ist, empfiehlt MySQL die Anzeige von 6 Ziffern. Das heißt, „234567“ „, aber die tatsächliche Anzahl der Anzeigeziffern wird von der Anwendung bestimmt. Die Anwendung kann den Vorschlag von MySQL akzeptieren, die letzten 6 Ziffern anzuzeigen, oder sie kann diesen Vorschlag ignorieren und die vollständigen 7 Ziffern anzeigen. Diese Breite wird zusammen mit dem Ergebnissatz an die Anwendung zurückgegeben werden
.

1.6.2 UNSIGNIERT

所有整数类型都可以有一个可选(非标准) UNSIGNED 属性。
无符号类型可用于在列中仅允许非负数,或者当您需要该列的较大数值范围时。例如,如果一列是 INT UNSIGNED ,则该列范围的大小(可表示的数字个数)相同,但其端点向上移动,从原来的1位表示符号和31位表示数值变为0位表示符号(即无符号位)和32位表示数值,可表示的数值范围从 -2147483648 到 2147483647 变为 从 0 到 4294967295 。

浮点和定点类型也可以是 UNSIGNED. 与整数类型一样,此属性可防止将负值存储在列中。与整数类型不同,列值的上限保持不变。

1.6.3 ZEROFILL

如果您为数字列指定 ZEROFILL ,MySQL 会自动添加 UNSIGNED 属性。

1.6.4 AUTO_INCREMENT

整数或浮点数据类型可以具有 AUTO_INCREMENT 属性。当您将 NULL 值插入带有 AUTO_INCREMENT 的索引列时,该列将设置为下一个序列值。通常这是 value+1,其中 value 是表中当前列的最大值。(AUTO_INCREMENT序列以 1 开头)

存储0到 AUTO_INCREMENT 列中的效果与存储 NULL 相同,除非启用了 NO_AUTO_VALUE_ON_ZERO 的 SQL 模式。
如果该列允许为 NULL ,则插入 NULL 到该列不会触发自增,而是将 NULL 插入到该列。
如果插入了一个正整数到该列,则会以该正整数为新的序列,以便下一个自增的值从该新的序列开始顺序排列。

实际操作:

create table tt (
	ID int(2) primary key AUTO_INCREMENT,
	name VARCHAR(1)
);
> OK

insert into tt VALUES (0, 'a'), (3, 'b'), (NULL, 'c');
> Affected rows: 3

select * from tt;
1	a 	# (0, 'a'), 插入id是0,但实际被自动自增为1。因为0与NULL一样都认为是非法的值,这种值遇上 AUTO_INCREMENT 就被认为需要mysql自增得到一个值
3	b 	# (3, 'b'), 指定了3作为id值,实际上3被采纳为ID值了。因为3是一个合法的数值,所以直接采纳,并将 AUTO_INCREMENT 的自增值记录为3,为下次自增做准备
4	c 	# (NULL, 'c'), 插入id是NULL,但实际被自动自增为4。因为上次已经将自增值改为3了,所以本次的自增是3+1=4

AUTO_INCREMENT 并不支持负值的列。

1.7 超出范围和溢出处理

当 MySQL 将值存储在列数据类型允许范围之外的数值列中时,结果取决于当时有效的 SQL 模式:

  • 如果启用严格的 SQL 模式,MySQL 会根据 SQL 标准拒绝超出范围的值并出错,并且插入失败。

  • 如果没有启用限制模式,MySQL 会将值裁剪到列数据类型范围的适当端点,并存储结果值。

    当将超出范围的值分配给整数列时,MySQL 仅存储与该列数据类型范围的对应的范围的值(这句话比较拗口,说人话:MySQL将根据二进制位截断高位,保留低位)。

    当为浮点或定点列分配的值超出指定(或默认)精度和小数位数所表示的范围时,MySQL 仅存储与该范围对应的值。(没太懂到底如何存?)

假设一个表t1有这个定义:

CREATE TABLE t1 (i1 TINYINT, i2 TINYINT UNSIGNED);

启用严格 SQL 模式(strict SQL mode )后,会出现超出范围的错误:

mysql> SET sql_mode = 'TRADITIONAL';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
ERROR 1264 (22003): Out of range value for column 'i1' at row 1
mysql> SELECT * FROM t1;
Empty set (0.00 sec)

在未启用严格 SQL 模式的情况下,会出现裁剪的警告:

mysql> SET sql_mode = '';
mysql> INSERT INTO t1 (i1, i2) VALUES(256, 256);
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'i1' at row 1 |
| Warning | 1264 | Out of range value for column 'i2' at row 1 |
+---------+------+---------------------------------------------+
mysql> SELECT * FROM t1;
+------+------+
| i1   | i2   |
+------+------+
|  127 |  255 |
+------+------+

未启用严格 SQL 模式时,由于裁剪而发生的列分配转换将报告为ALTER TABLELOAD DATAUPDATE和多行 INSERT语句的警告。
在严格模式下,这些语句会失败,部分或全部值不会被插入或更改,这取决于表是否为事务表等因素。有关详细信息,请参阅 “服务器 SQL 模式”

数值表达式求值期间的溢出会导致错误。例如,最大有符号 BIGINT值为 9223372036854775807,因此以下表达式会产生错误:

mysql> SELECT 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'

要在这种情况下使操作成功,请将值转换为无符号;

mysql> SELECT CAST(9223372036854775807 AS UNSIGNED) + 1;
+-------------------------------------------+
| CAST(9223372036854775807 AS UNSIGNED) + 1 |
+-------------------------------------------+
|                       9223372036854775808 |
+-------------------------------------------+

是否发生溢出取决于操作数的范围,因此处理上述表达式的另一种方法是使用精确值算术,因为 DECIMAL值的范围比整数更大:

mysql> SELECT 9223372036854775807.0 + 1;
+---------------------------+
| 9223372036854775807.0 + 1 |
+---------------------------+
|     9223372036854775808.0 |
+---------------------------+

整数值之间的减法,其中一个是 UNSIGNED 类型,默认情况下会产生无符号结果。如果结果是负数,则会导致错误:

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'

如果启用 NO_UNSIGNED_SUBTRACTION SQL 模式,则结果是负数,而不会出现错误:

mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
|                      -1 |
+-------------------------+

如果此类操作的结果用于更新 UNSIGNED整数列,则结果将被裁剪为列类型的最大值,或者如果NO_UNSIGNED_SUBTRACTION 启用,则裁剪为 0。如果启用严格的 SQL 模式,则会发生错误并且列保持不变。

2、日期和时间数据类型 (5种)

2.1 日期和时间数据类型语法

2.2 DATE、DATETIME 和 TIMESTAMP 类型

2.3 TIME 类型

2.4 年份类型

2.5 2 位 YEAR(2) 限制和迁移到 4 位 YEAR

2.6 TIMESTAMP 和 DATETIME 的自动初始化和更新

2.7 时间值中的小数秒

2.8 日期和时间类型之间的转换

2.9 2 位数年份日期

用于表示时间值的日期和时间数据类型是 DATETIMEDATETIMETIMESTAMPYEAR。每种时间类型都有一个有效值范围,以及一个“零”值,当您指定 MySQL 无法表示的无效值时,可以使用该“零”值。TIMESTAMPDATETIME 类型具有特殊的自动更新行为,在 第2.6 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新” 中进行了描述。

有关临时数据类型的存储要求的信息,请参阅 “数据类型存储要求”

有关对时间值进行操作的函数的描述,请参阅 “日期和时间函数”

使用日期和时间类型时,请记住以下一般注意事项:

  • MySQL ruft Werte eines bestimmten Datums- oder Zeittyps im Standardausgabeformat ab, versucht jedoch, verschiedene Formate für die von Ihnen bereitgestellten Eingabewerte zu interpretieren (z. B. wenn Sie einen Wert angeben, der einem Datum zugewiesen oder mit diesem verglichen werden soll). Zeittyp). Eine Beschreibung der zulässigen Formate für Datums- und Uhrzeittypen finden Sie unter Datums- und Zeitliterale . Erwarten Sie gültige Werte von Ihnen. Wenn Sie Werte in anderen Formaten verwenden, kann es zu unvorhersehbaren Ergebnissen kommen.

  • Obwohl MySQL versucht, Werte in verschiedenen Formaten zu interpretieren, muss der Datumsteil immer in der Reihenfolge Jahr-Monat-Tag (z. B. '98-09-04') und nicht in der Reihenfolge Monat-Tag-Jahr oder Tag-Monat-Jahr angegeben werden Wird häufig anderswo verwendet (z. B. '09-04-98',, '04-09-98'). STR_TO_DATE()Diese Funktion kann nützlich sein , um Zeichenfolgen in einer anderen Reihenfolge in die Reihenfolge Jahr, Monat, Tag umzuwandeln .

  • Daten mit zweistelligen Jahresangaben sind nicht eindeutig, da das Jahrhundert unbekannt ist. MySQL verwendet die folgenden Regeln, um zweistellige Jahreswerte zu interpretieren:

    • 70-99Die Jahreswerte im Bereich werden zu 1970-1999.
    • 00-69Die Jahreswerte im Bereich werden zu 2000-2069.

    Siehe auch Abschnitt 2.9, „Zweistellige Jahreszahlen in Datumsangaben“ .

  • Konvertiert einen Wert von einem Zeittyp in einen anderen gemäß den Regeln in Abschnitt 2.8, „Konvertierungen zwischen Datums- und Zeittypen“ .

  • MySQL wandelt einen Datums- oder Zeitwert automatisch in eine Zahl um, wenn der Wert in einem numerischen Kontext verwendet wird, und umgekehrt.

  • Wenn MySQL auf einen Wert eines Datums- oder Zeittyps stößt, der außerhalb des gültigen Bereichs liegt oder für diesen Typ ungültig ist, konvertiert es den Wert standardmäßig in den „Null“-Wert dieses Typs. Die Ausnahme besteht darin, dass Werte außerhalb des Bereichs TIMEauf den entsprechenden TIMEBereich begrenzt werden.

  • Indem Sie den SQL-Modus auf den entsprechenden Wert einstellen, können Sie die Datumstypen, die MySQL unterstützen soll, genauer angeben. (Siehe „Server-SQL-Modus“.ALLOW_INVALID_DATES ) Sie können MySQL bestimmte Daten akzeptieren lassen , indem Sie beispielsweise den SQL-Modus aktivieren '2009-11-31'. Dies ist nützlich, wenn Sie vom Benutzer angegebene „möglicherweise falsche“ Werte in einer Datenbank (z. B. in einem Webformular) für die zukünftige Verarbeitung speichern möchten. In diesem Modus überprüft MySQL nur, ob der Monat im Bereich von 1 bis 12 und der Tag im Bereich von 1 bis 31 liegt.

  • Mit MySQL können Sie Tag oder Monat und Tag mit Null in der Spalte DATE„oder“ DATETIMEspeichern . Dies ist nützlich für Anwendungen, die Geburtstage speichern müssen, deren genaues Datum Sie möglicherweise nicht kennen. In diesem Fall speichern Sie das Datum einfach als '2009-00-00'oder '2009-01-00'. Sie sollten jedoch keine korrekten Ergebnisse für diese Datumsangaben erwarten, wie z. B. die Funktionen DATE_SUB()oder DATE_ADD(), die ein vollständiges Datum erfordern. NO_ZERO_IN_DATEAktivieren Sie diesen Modus , um den Null-Monats- oder Tagesteil des Datums zu unterdrücken .

  • Mit MySQL können Sie '0000-00-00'solche „Null“-Werte als „Dummy-Daten“ speichern. In einigen Fällen ist dies NULLpraktischer als die Verwendung von Werten und verbraucht weniger Daten- und Indexspeicherplatz. Um ihn zu deaktivieren '0000-00-00', aktivieren Sie diesen NO_ZERO_DATEModus.

  • „Null“-Datums- oder Zeitwerte, die über Connector/ODBC verwendet werden, werden automatisch konvertiert, NULLda ODBC diese Werte nicht verarbeiten kann.

下表显示了每种类型的“零” 值的格式。“零”值是特殊的,但您可以使用表中显示的值显式存储或引用它们。您也可以使用更容易编写的值 '0'0 来表示“零”值。对于包含日期部分( DATEDATETIMETIMESTAMP )的时间类型使用这些值可能会产生警告或错误。确切的行为取决于启用了严格模式和 NO_ZERO_DATE SQL 模式中的哪一个(如果有);请参阅“服务器 SQL 模式”

数据类型 “零”值
DATE '0000-00-00'
TIME '00:00:00'
DATETIME '0000-00-00 00:00:00'
TIMESTAMP '0000-00-00 00:00:00'
YEAR 0000

2.1 日期和时间数据类型语法

用于表示时间值的日期和时间数据类型是DATETIMEDATETIMETIMESTAMPYEAR

对于DATEDATETIME 的范围描述, “ supported ”表示虽然早期的值可能有效(能工作),但不能保证。

MySQL 允许 TIMEDATETIMETIMESTAMP 值的小数秒, 精度高达微秒(6 位数字)。要定义包含小数秒部分的列,请使用语法 type_name(fsp) ,其中 type_nameTIMEDATETIMETIMESTAMPfsp 是小数秒精度。例如:

CREATE TABLE t1 (t TIME(3), dt DATETIME(6), ts TIMESTAMP(0));

该*fsp*值(如果给定)必须在 0 到 6 的范围内。值 0 表示没有小数部分。如果省略,则默认精度为 0。(这与标准 SQL 默认值 6 不同,以便与以前的 MySQL 版本兼容。)

表中的任何TIMESTAMPDATETIME列都可以具有自动初始化和更新属性;请参阅 第 2.6 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新”

2.1.1 DATE

日期。 “ supported ”的范围是 '1000-01-01' to '9999-12-31'。MySQL 以 ‘YYYY-MM-DD’ 格式显示 DATE 的值 ,但允许使用字符串数字将值分配给 DATE 列。

2.1.2 DATETIME[(fsp)]

日期和时间组合。“ supported ”的范围是 '1000-01-01 00:00:00.000000' to '9999-12-31 23:59:59.999999'。MySQL 以 'YYYY-MM-DD hh:mm:ss[.fraction]' 格式显示 DATETIME 值 ,但允许使用字符串或数字将值分配给 DATETIME 列。

可选值 *fsp*可以给出 0 到 6 范围的数字来指定小数秒精度。值 0 表示没有小数部分。如果省略,则默认精度为 0。

可以使用 DEFAULTON UPDATE 列定义子句指定 DATETIME 列的自动初始化和更新到当前日期和时间 ,如 第 2.6 节,“TIMESTAMP 和 DATETIME 的自动初始化和更新” 中所述。

2.1.3 TIMESTAMP[(fsp)]

Zeitstempel. Der Bereich ist '1970-01-01 00:00:01.000000'UTC bis '2038-01-19 03:14:07.999999'UTC. TIMESTAMPDer Wert wird als Anzahl der Sekunden seit der Epoche ( '1970-01-01 00:00:00'UTC) gespeichert TIMESTAMP. Ein Zeitstempel kann keinen Wert darstellen '1970-01-01 00:00:00', da dieser 0 Sekunden ab der Epoche entspricht, aber der Wert 0 ist für die Darstellung '0000-00-00 00:00:00'dieses „Null“-Wertes reserviert.

Optionale Werte* fsp*Eine Zahl im Bereich von 0 bis 6 kann angegeben werden, um die Genauigkeit in Sekundenbruchteilen anzugeben. Ein Wert von 0 bedeutet keinen Dezimalteil. Wenn es weggelassen wird, ist die Standardgenauigkeit 0.

Die Art und Weise, wie die Serververarbeitung TIMESTAMPdefiniert wird, hängt vom explicit_defaults_for_timestampWert einer Systemvariablen ab (siehe „Server-Systemvariablen“ ).

  • Wenn diese Option aktiviert ist, wird das Attribut „oder“ explicit_defaults_for_timestampkeiner Spalte automatisch zugewiesen . Sie müssen explizit in die Spaltendefinition einbezogen werden. Darüber hinaus ist jede Spalte zulässig, die nicht explizit als Wert deklariert ist .DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMPNOT NULLNULL

  • Wenn die explicit_defaults_for_timestampOption deaktiviert ist, behandelt der Server TIMESTAMPdies wie folgt:
    Sofern nicht anders angegeben, TIMESTAMPwird die Spalte automatisch auf das Datum und die Uhrzeit der letzten Änderung festgelegt, wenn der ersten Spalte in einer Tabelle nicht explizit ein Wert zugewiesen wird. Dadurch eignet sich die Spalte TIMESTAMPzum Aufzeichnen von Zeitstempeln von INSERTODER- Operationen. Sie können eine Spalte auch auf das aktuelle Datum und die aktuelle Uhrzeit einstellen, indem Sie ihr einen Wert UPDATEzuweisen , es sei denn, sie wurde so definiert, dass Werte zulässig sind.NULLTIMESTAMPNULL

Die automatische Initialisierung und Aktualisierung auf das aktuelle Datum und die aktuelle Uhrzeit kann mithilfe der Spaltendefinitionsklauseln DEFAULT CURRENT_TIMESTAMPund angegeben werden. Wie bereits erwähnt, verfügt die erste Spalte standardmäßig über diese Eigenschaften. Es kann jedoch jede beliebige Spalte in der Tabelle so definiert werden, dass sie über diese Eigenschaften verfügt.ON UPDATE CURRENT_TIMESTAMPTIMESTAMPTIMESTAMP

2.1.4TIME[(fsp)]

Zeit. Die Reichweite liegt '-838:59:59.000000'bei '838:59:59.000000'. MySQL zeigt Werte im Format „ hh:mm:ss[. ]“ an , ermöglicht jedoch die Verwendung von Zeichenfolgen oder Zahlen zum Zuweisen von Werten zu Spalten.fractionTIMETIME

Optionale Werte* fsp*Eine Zahl im Bereich von 0 bis 6 kann angegeben werden, um die Genauigkeit in Sekundenbruchteilen anzugeben. Ein Wert von 0 bedeutet keinen Dezimalteil. Wenn es weggelassen wird, ist die Standardgenauigkeit 0.

2.1.5YEAR[(4)]

Jahr im 4-stelligen Format. MySQL YYYYzeigt YEARWerte im Format an, ermöglicht jedoch die Zuweisung von Werten zu YEARSpalten mithilfe von Zeichenfolgen oder Zahlen. YEARWerte werden angezeigt als: 1901, 2155oder 0000.

Beachten:

YEAR(2)Dieser Datentyp ist veraltet und die Unterstützung wurde in MySQL 5.7.5 entfernt. Informationen zum Konvertieren einer 2-Bit-Spalte YEAR(2)in eine 4-Bit-Spalte YEARfinden Sie in Abschnitt 2.5, „2-Bit-YEAR(2)-Einschränkungen und Migration zu 4-Bit-YEAR“ .

Weitere Informationen zum YEARAnzeigeformat und zur Interpretation von Eingabewerten finden Sie in Abschnitt 2.4, „YEAR-Typ“ .

2.1.6 Zusätzliche Hinweise zu Zeitwerten

聚合函数SUM()AVG() 不适用于时间值。(他们将值转换为数字,在第一个非数字字符之后丢失所有内容。)要解决此问题,请转换为数字单位,执行聚合操作,然后转换回时间值。例子:

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;

注意:

MySQL 服务器在启用 MAXDB SQL 模式的情况下,TIMESTAMPDATETIME 相同。如果在创建表时启用此模式,则将 TIMESTAMP列创建为DATETIME列。因此,此类列使用 DATETIME显示格式,具有相同的值范围,并且不会自动初始化或更新到当前日期和时间。请参阅 “服务器 SQL 模式”

自 MySQL 5.7.22 起,MAXDB已弃用;将在 MySQL 的未来版本中删除。

2.2 DATE、DATETIME 和 TIMESTAMP 类型

DATEDATETIMETIMESTAMP 类型是相关的。 本节介绍它们的特征、它们的相似之处以及它们的不同之处。MySQL 可以识别 DATEDATETIMETIMESTAMP 的多种格式的值,更多信息参考 “日期和时间文字” 。对于 DATEDATETIME 范围描述,“ supported ”表示虽然早期的值可能有效,但不能保证。

DATE类型用于具有日期部分但没有时间部分的值。 MySQL 以 'YYYY-MM-DD' 格式检索和显示 DATE 类型的值 。支持的范围是 '1000-01-01' to '9999-12-31'

DATETIMETyp, der für Werte verwendet wird, die sowohl Datums- als auch Zeitkomponenten enthalten. MySQL ruft Werte im Format 'YYYY-MM-DD hh:mm:ss'ab und zeigt sie an . DATETIMEDer unterstützte Bereich liegt '1000-01-01 00:00:00'zwischen '9999-12-31 23:59:59'.

TIMESTAMPTyp, der für Werte verwendet wird, die sowohl Datums- als auch Zeitkomponenten enthalten. TIMESTAMPHat einen Bereich von '1970-01-01 00:00:01'UTC bis '2038-01-19 03:14:07'UTC.

Ein DATETIMEOR- TIMESTAMPWert kann eine nachgestellte Sekundenbruchteilkomponente mit einer Genauigkeit von bis zu Mikrosekunden (6 Ziffern) enthalten. Insbesondere wird jeder Bruchteil des in DATETIMEdie Spalte oder eingefügten Werts gespeichert und nicht verworfen. TIMESTAMPNach Einbeziehung des Dezimalteils lautet das Format dieser Werte: 'YYYY-MM-DD hh:mm:ss[.fraction]'Typwertbereich DATETIMEist '1000-01-01 00:00:00.000000'bis '9999-12-31 23:59:59.999999', TIMESTAMPTypwertbereich ist '1970-01-01 00:00:01.000000'bis '2038-01-19 03:14:07.999999'. Der Nachkommateil sollte immer durch einen Dezimalpunkt vom Rest der Zeit getrennt werden; andere Sekundenbruchteiltrenner werden nicht erkannt. Informationen zur Unterstützung von Sekundenbruchteilen in MySQL finden Sie in Abschnitt 2.7, „Sekundenbruchteile in Zeitwerten“ .

TIMESTAMPund DATETIMEDatentypen ermöglichen eine automatische Initialisierung und Aktualisierung auf das aktuelle Datum und die aktuelle Uhrzeit. Weitere Informationen finden Sie in Abschnitt 2.6, „Automatische Initialisierung und Aktualisierung von TIMESTAMP und DATETIME“ .

MySQL TIMESTAMPkonvertiert Werte aus der aktuellen Zeitzone zur Speicherung in UTC und konvertiert dann Werte von UTC zum Abruf zurück in die aktuelle Zeitzone. (Dies ist bei anderen Typen nicht der Fall, z. B. DATETIME) Standardmäßig ist die aktuelle Zeitzone für jede Verbindung die Zeit des Servers. Die Zeitzone kann pro Verbindung eingestellt werden. Solange die Zeitzoneneinstellung unverändert bleibt, können Sie den gleichen gespeicherten Wert zurückgeben. Wenn Sie einen TIMESTAMPWert speichern, dann die Zeitzone ändern und den Wert abrufen, unterscheidet sich der abgerufene Wert von dem von Ihnen gespeicherten Wert. Dies liegt daran, dass für die Konvertierung in beide Richtungen nicht dieselbe Zeitzone verwendet wird. Die aktuelle Zeitzone steht als time_zoneSystemvariable zur Verfügung. Weitere Informationen finden Sie unter MySQL Server-Zeitzonenunterstützung . Wenn das
SQL-Schema diese Konvertierung zulässt, wird ein ungültiger DATEoder- Wert in einen Nullwert ( or ) des entsprechenden Typs konvertiert. Das genaue Verhalten hängt davon ab, ob der strikte SQL-Modus aktiviert ist und welcher SQL-Modus aktiviert ist; siehe Server-SQL-Modus .DATETIMETIMESTAMP'0000-00-00''0000-00-00 00:00:00'NO_ZERO_DATE

Bitte beachten Sie bestimmte Eigenschaften der Datumswertinterpretation in MySQL:

  • MySQL ermöglicht die Angabe von Werten als „entspanntes“ Format von Zeichenfolgen, wobei beliebige Satzzeichen als Trennzeichen zwischen Datums- oder Uhrzeitteilen verwendet werden können. Diese Syntax kann in manchen Fällen irreführend sein. Beispielsweise '10:11:12'kann ein Wert wie ein Zeitwert aussehen, weil er verwendet wird :, aber wenn er in einem Datumskontext verwendet wird, '2010-11-12'wird er als Jahr interpretiert. Der Wert '10:45:15'wird konvertiert, '0000-00-00'da '45'es sich nicht um einen gültigen Monat handelt.

    Das einzige anerkannte Trennzeichen zwischen den Datums- und Uhrzeitteilen und den Sekundenbruchteilen ist der Dezimalpunkt.

  • Der Server verlangt, dass die Monats- und Tageswerte gültig sind und nicht nur in den Bereichen 1 bis 12 bzw. 1 bis 31 liegen. '2004-04-31'Wenn der strikte Modus deaktiviert ist, wird dies in ein ungültiges Datum umgewandelt '0000-00-00'und eine Warnung generiert, da der April keinen 31. hat. Wenn der strikte Modus aktiviert ist, wird bei ungültigen Daten ein Fehler generiert. Um solche Daten zuzulassen, aktivieren Sie ALLOW_INVALID_DATES. Weitere Informationen finden Sie unter Server-SQL-Modus .

  • MySQL akzeptiert keine TIMESTAMPWerte, die Nullen in Tages- oder Monatsspalten enthalten oder keine gültigen Datumsangaben sind. Die einzige Ausnahme von dieser Regel ist der spezielle Wert „Null“, wenn der SQL-Modus diesen Wert zulässt. '0000-00-00 00:00:00'Das genaue Verhalten hängt davon ab, ob der strikte SQL-Modus aktiviert ist und NO_ZERO_DATEwelcher SQL-Modus aktiviert ist; siehe Server-SQL-Modus .

  • Daten mit zweistelligen Jahresangaben sind nicht eindeutig, da das Jahrhundert unbekannt ist. MySQL verwendet die folgenden Regeln, um zweistellige Jahreswerte zu interpretieren:

    • Die Jahreswerte im Bereich 00-69werden zu 2000-2069.
    • Die Jahreswerte im Bereich 70-99werden zu 1970-1999.

Siehe auch Abschnitt 2.9, „Zweistellige Jahreszahlen in Datumsangaben“ .

2.3 TIME-Typ

MySQL ruft Werte im 'hh:mm:ss'Format ab und zeigt sie an (oder 'hhh:mm:ss'im Format für große „Stunden“-Werte) . Die Werte können von bis reichen . Der Stundenteil kann groß sein, da der Typ nicht nur zur Darstellung einer Tageszeit (muss weniger als 24 Stunden betragen), sondern auch einer verstrichenen Zeit oder eines Zeitintervalls zwischen zwei Ereignissen (die viel größer als 24 Stunden sein kann) verwendet werden kann , sogar negative Zahlen).TIMETIME'-838:59:59''838:59:59'TIME

MySQL erkennt TIMEverschiedene Werteformate, von denen einige eine nachgestellte Sekundenbruchteilkomponente mit einer Genauigkeit von bis zu Mikrosekunden (6 Ziffern) enthalten können. Siehe „Datums- und Zeitliterale“ . Informationen zur Unterstützung von Sekundenbruchteilen in MySQL finden Sie in Abschnitt 2.7, „Sekundenbruchteile in Zeitwerten“ . Insbesondere TIMEwird jeder Bruchteil des in die Spalte eingefügten Werts gespeichert und nicht verworfen. Einschließlich des Dezimalteils TIMEreichen die Werte von '-838:59:59.000000'bis '838:59:59.000000'.

Seien Sie vorsichtig, wenn Sie Spalten TIMEabgekürzte Zeitwerte zuweisen . MySQL interpretiert Zeitabkürzungswerte mit Doppelpunkt als Tageszeit. Das heißt, '11:12'bedeutet '11:12:00', ist nicht '00:11:12'. MySQL interpretiert abgekürzte Werte ohne Doppelpunkte unter der Annahme, dass die beiden Ziffern ganz rechts Sekunden darstellen (d. h. als verstrichene Zeit und nicht als Tageszeit) . Beispielsweise könnten Sie '1112'and als (12 Minuten nach 11 Uhr) 1112anzeigen '11:12:00', MySQL interpretiert sie jedoch als '00:11:12'(11 Minuten, 12 Sekunden). Ebenso werden '12'und 12interpretiert als '00:00:12'. (Persönliche Zusammenfassung: Zeitwerte mit Doppelpunkten werden von links nach rechts in der Reihenfolge „Stunden, Minuten und Sekunden“ analysiert , und rein numerische Zeitwerte ohne Doppelpunkte werden von rechts nach links in der Reihenfolge „Sekunden“ analysiert. Minuten und Stunden")

Das einzige anerkannte Trennzeichen zwischen dem Zeitteil und dem Sekundenbruchteil ist der Dezimalpunkt.

默认情况下,位于TIME 范围之外但在其他方面有效的值将被剪裁到范围的最近端点。例如, '-850:00:00'and '850:00:00'被转换为 '-838:59:59'and '838:59:59'。无效TIME 值转换为'00:00:00'. 请注意,因为'00:00:00'它本身是一个有效值 TIME,所以无法根据存储在表中的 '00:00:00' 值来判断是原始值无效转换而来,还是原始值就是 '00:00:00'

要对无效 TIME 值进行更严格的处理,请启用严格的 SQL 模式以导致错误发生。请参阅 “服务器 SQL 模式”

2.4 年份类型

YEAR 类型是用于表示年份值的 1 字节类型。可以将其声明为 YEAR具有 4 个字符的隐式显示宽度,或者等效地声明为YEAR(4)具有显式显示宽度。

注意

2 位 YEAR(2) 数据类型已被弃用,并且在 MySQL 5.7.5 中删除了对它的支持。要将 2 位 YEAR(2) 列转换为 4 位 YEAR 列,请参阅 第 2.5 节,“2 位 YEAR(2) 限制和迁移到 4 位 YEAR”

MySQL 以 YYYY 格式显示 YEAR 值, 范围为 1901 to21550000.

YEAR接受多种格式的输入值:

  • '1901''2155' 范围内的 4 位字符串

  • 1901zu einer 4- stelligen Zahl2155 im Bereich .

  • '0'Eine einstellige oder zweistellige Zeichenfolge'99' im Bereich bis . MySQL konvertiert Werte im to- Bereich in Werte in to und Werte im to- Bereich in Werte in to .'0''69'20002069YEAR'70''99'19701999YEAR

  • 0zu 99einer 1- oder 2- stelligen Zahl im Bereich . MySQL konvertiert Werte im 1to- 69Bereich in Werte in 2001to und Werte im to- Bereich in Werte in to .2069YEAR709919701999YEAR

    Das Einfügen der Zahl 0hat einen angezeigten Wert von 0000und einen internen Wert von 0000. Wenn Sie Nullen einfügen und diese interpretieren möchten 2000, geben Sie sie als Zeichenfolge '0' oder an '00'.

  • Als YEARErgebnis einer Funktion, die im Kontext akzeptable Werte zurückgibt, NOW()z.

Wenn der strikte SQL-Modus nicht aktiviert ist, konvertiert MySQL YEARungültige Werte in 0000. Im strikten SQL-Modus führt der Versuch, einen ungültigen Wert einzufügen, YEARzu einem Fehler.

另请参见第 2.9 节,“日期中的两位数年份”

2.5 2 位 YEAR(2) 限制和迁移到 4 位 YEAR

本节介绍使用 2 位YEAR(2)数据类型时可能出现的问题,并提供有关将现有 YEAR(2)列转换为 4 位年份值列的信息,可以将其声明为 YEAR 隐式显示宽度为 4 个字符,或等效地声明YEAR(4)为显式显示宽度。

尽管 YEAR/YEAR(4) 和废弃的YEAR(2)类型的内部值范围相同(1901 to 21550000),但显示宽度 YEAR(2)使该类型内在的歧义,因为显示的值仅指示内部值的最后两位数字并省略世纪数字。在某些情况下,结果可能会导致信息丢失。出于这个原因,请避免 YEAR(2)在您的应用程序中使用并在需要year值数据类型的任何地方使用YEAR/YEAR(4)。从 MySQL 5.7.5 开始,移除对 YEAR(2) 的支持,现有的 2 位列YEAR(2) 必须转换为 4 位 YEAR列再次可用。

2.5.1 YEAR(2) 的限制

YEAR(2) 数据类型的问题包括显示值的歧义,以及在转储和重新加载值或转换为字符串时可能丢失信息。

  • 显示YEAR(2)的值可能不明确。最多三个 YEAR(2)具有不同内部值的值可能具有相同的显示值,如以下示例所示:

    mysql> CREATE TABLE t (y2 YEAR(2), y4 YEAR);
    Query OK, 0 rows affected, 1 warning (0.01 sec)
    
    mysql> INSERT INTO t (y2) VALUES(1912),(2012),(2112);
    Query OK, 3 rows affected (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    
    mysql> UPDATE t SET y4 = y2;
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 3  Changed: 3  Warnings: 0
    
    mysql> SELECT * FROM t;
    +------+------+
    | y2   | y4   |
    +------+------+
    |   12 | 1912 |
    |   12 | 2012 |
    |   12 | 2112 |
    +------+------+
    3 rows in set (0.00 sec)
    
  • Wenn Sie mysqldump verwenden , um die im vorherigen Beispiel erstellte Tabelle zu sichern, y2verwendet die Dump-Datei dieselben 2 Bits ( 12) für alle Werte. Wenn die Tabelle aus der Dump-Datei neu geladen wird, haben alle generierten Zeilen einen internen Wert von 2012und einen angezeigten Wert von 12, sodass die Unterscheidung zwischen ihnen verloren geht.

  • Konvertiert einen zweistelligen oder vierstelligen YEARDatenwert in eine Zeichenfolgenform und verwendet seinen Datentyp, um die Breite anzuzeigen. Angenommen, eine YEAR(2)Spalte und eine YEAR/ YEAR(4)-Spalte enthalten beide 1970Werte. Dann erhalten sie jeweils die Zeichenfolgenergebnisse von '70'und '1970'. Das heißt, bei der Konvertierung von einem internen Wert in eine Zeichenfolge gehen Informationen verloren.

  • Beim Einfügen in eine Spalte CSVeiner Tabelle werden Werte außerhalb des to- Bereichs falsch gespeichert. Das Einfügen würde beispielsweise zu einem angezeigten Wert von führen , aber zu einem internen Wert von .YEAR(2)197020692211112011

Um diese Probleme zu vermeiden, verwenden Sie 4-Bit- YEARoder YEAR(4)Datentypen anstelle von 2-Bit- YEAR(2)Datentypen. Empfehlungen für Migrationsstrategien finden Sie weiter unten in diesem Abschnitt.

(TODO: nicht abgeschlossen)

2.6 Automatische Initialisierung und Aktualisierung von TIMESTAMP und DATETIME

TIMESTAMPund DATETIMESpalten können automatisch initialisiert und auf das aktuelle Datum und die aktuelle Uhrzeit (d. h. den aktuellen Zeitstempel) aktualisiert werden.

TIMESTAMPFür jede Spalte in der Tabelle DATETIMEkönnen Sie den aktuellen Zeitstempel als Standardwert für die automatische Aktualisierung angeben:

  • Automatisch initialisierte Spalten werden auf den aktuellen Zeitstempel der eingefügten Zeilen gesetzt, denen der Spalte kein Wert zugewiesen ist.
  • Eine automatisch aktualisierte Spalte wird automatisch auf den aktuellen Zeitstempel aktualisiert, wenn sich der Wert einer anderen Spalte in der Zeile von ihrem aktuellen Wert ändert. Wenn alle anderen Spalten auf ihre aktuellen Werte gesetzt werden, bleiben automatisch aktualisierte Spalten unverändert. Um zu verhindern, dass eine automatisch aktualisierte Spalte aktualisiert wird, wenn sich andere Spalten ändern, legen Sie sie explizit auf ihren aktuellen Wert fest. Um eine automatisch aktualisierte Spalte zu aktualisieren, wenn sich andere Spalten nicht geändert haben, legen Sie sie explizit auf den Wert fest, den sie haben sollte (z. B. auf CURRENT_TIMESTAMP).

Wenn Systemvariablen deaktiviert sind, können Sie außerdem jede Spalte (außer ) mit dem aktuellen Datum und der aktuellen Uhrzeit initialisieren oder aktualisieren, explicit_defaults_for_timestampindem Sie ihr einen Wert zuweisen , es sei denn, sie wurde so definiert, dass sie einen Wert zulässt.TIMESTAMPDATETIMENULLNULL

Um automatische Eigenschaften anzugeben, verwenden Sie DEFAULT CURRENT_TIMESTAMPdie ON UPDATE CURRENT_TIMESTAMPKlauseln in der Spaltendefinition. Die Reihenfolge der Klauseln spielt keine Rolle. Wenn beide in der Spaltendefinition vorhanden sind, kann eine von beiden zuerst erscheinen. CURRENT_TIMESTAMPAlle Synonyme für CURRENT_TIMESTAMPhaben die gleiche Bedeutung wie . Sie sind CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMPund LOCALTIMESTAMP().

(TODO: Nicht abgeschlossen, der Rest ist die detaillierte Beschreibung der NULL-Werte und Standardwerte)

2,7 Sekundenbruchteile in Zeitwerten

2.8 Konvertierung zwischen Datums- und Uhrzeittypen

2.9 2-stelliges Jahresdatum

3. String-Datentyp

3.1 Syntax des String-Datentyps

3.2 CHAR- und VARCHAR-Typen

3.3 BINARY- und VARBINARY-Typen

3.4 BLOB- und TEXT-Typen

3.5 ENUM-Typ

3.6 SET-Typ

3.1 Syntax des String-Datentyps

3.2 CHAR- und VARCHAR-Typen

3.3 BINARY- und VARBINARY-Typen

3.4 BLOB- und TEXT-Typen

3.5 ENUM-Typ

3.6 SET-Typ

4. Räumliche Datentypen

4.1 Räumliche Datentypen

4.2 Geometrisches OpenGIS-Modell

4.3 Unterstützte Geodatenformate

4.4 Geometrische Wohlgeformtheit und Gültigkeit

4.5 Erstellen Sie räumliche Spalten

4.6 Raumspalten füllen

4.7 Erhalten räumlicher Daten

4.8 Optimierung der räumlichen Analyse

4.9 Räumlichen Index erstellen

4.10 Verwendung räumlicher Indizes

4.1 Räumliche Datentypen

4.2 Geometrisches OpenGIS-Modell

4.3 Unterstützte Geodatenformate

4.4 Geometrische Wohlgeformtheit und Gültigkeit

4.5 Erstellen Sie räumliche Spalten

4.6 Raumspalten füllen

4.7 Erhalten räumlicher Daten

4.8 Optimierung der räumlichen Analyse

4.9 Räumlichen Index erstellen

4.10 Verwendung räumlicher Indizes

5. JSON-Datentyp

5.1. JSON-Werte erstellen
5.2. Normalisierung, Zusammenführung und automatische Verpackung von JSON-Werten
5.3. JSON-Werte suchen und ändern
5.4. JSON-Pfadsyntax
5.5. Vergleich und Sortierung von JSON-Werten
5.6. Konvertieren zwischen JSON und Nicht-JSON-Werte
5.7. JSON-Aggregation von Werten
5.8, verwandte Referenzen

Ab MySQL 5.7.8 unterstützt MySQL native Datentypen, die durch RFC 7159JSON definiert sind und effektiv auf Daten in JSON-Dokumenten (JavaScript Object Notation) zugreifen können. Dieser Datentyp bietet gegenüber dem Speichern von JSON-formatierten Zeichenfolgen in einer Zeichenfolgenspalte die folgenden Vorteile:

  • Validieren Sie in Spalten gespeicherte JSON-Dokumente automatisch JSON. Ungültige Dokumente führen zu Fehlern.
  • Optimiertes Speicherformat. In Spalten gespeicherte JSON-Dokumente JSONwerden in ein internes Format konvertiert, das ein schnelles Lesen von Dokumentelementen ermöglicht. Wenn der Server später einen in diesem Binärformat gespeicherten JSON-Wert lesen muss, muss er den Wert nicht aus der Textdarstellung analysieren. Die Struktur des Binärformats ermöglicht es dem Server, Unterobjekte oder verschachtelte Werte direkt nach Schlüssel oder Array-Index zu suchen, ohne alle Werte davor oder danach im Dokument lesen zu müssen.

JSONDer zum Speichern eines Dokuments erforderliche Speicherplatz entspricht in etwa dem LONGBLOBoder LONGTEXT; Einzelheiten finden Sie in Abschnitt 7, „Speicheranforderungen für Datentypen“ . JSONEs ist wichtig zu bedenken, dass die Größe jedes in einer Spalte gespeicherten JSON-Dokuments durch max_allowed_packetden Wert der Systemvariablen begrenzt ist. (Er kann größer als dieser Wert sein, wenn der Server JSON-Werte intern im Speicher manipuliert; der Grenzwert gilt, wenn der Server ihn speichert.)

Spalten JSONdürfen keine Nicht- NULLStandardwerte haben.

Zusätzlich zu JSONden Datentypen gibt es eine Reihe von SQL-Funktionen, die Vorgänge an JSON-Werten ermöglichen, beispielsweise das Erstellen, Bearbeiten und Suchen. Die folgende Diskussion zeigt Beispiele für diese Operationen. Einzelheiten zu einzelnen Funktionen finden Sie in Abschnitt 12.18, „JSON-Funktionen“ .

Außerdem wird eine Reihe räumlicher Funktionen zum Bearbeiten von GeoJSON-Werten bereitgestellt. Siehe räumliche GeoJSON-Funktionen .

JSONSpalten werden wie andere binäre Spalten nicht direkt indiziert. Stattdessen erstellen Sie einen Index für die generierte Spalte, um JSONeinen Skalarwert aus der Spalte zu extrahieren. Ein detailliertes Beispiel finden Sie unter Indizieren generierter Spalten zur Bereitstellung von JSON-Spaltenindizes.

Der MySQL-Optimierer sucht auch nach kompatiblen Indizes für virtuelle Spalten, die mit JSON-Ausdrücken übereinstimmen.

MySQL NDB Cluster 7.5 (7.5.2 und höher) unterstützt Spalten und MySQL-JSON-Funktionen, einschließlich der Erstellung von Indizes für JSONaus Spalten generierte Spalten als Workaround für Spalten, die nicht indiziert werden können. Jede Tabelle unterstützt bis zu 3 Spalten.JSONJSONNDBJSON

Die nächsten Abschnitte enthalten grundlegende Informationen zur Erstellung und Bearbeitung von JSON-Werten.

5.1、创建 JSON 值

JSON 数组包含由逗号分隔并包含在[] 字符中的值列表:

["abc", 10, null, true, false]

JSON 对象包含一组键值对,由逗号分隔并包含在{ }字符中:

{
    
    "k1": "value", "k2": 10}

如示例所示,JSON 数组和对象可以包含标量值,即字符串或数字、JSON 空字面量或 JSON 布尔真或假字面量。JSON 对象中的键必须是字符串。时间(日期、时间或日期时间)标量值也是允许的:

["12:18:29.000000", "2015-07-29", "2015-07-29 12:18:29.000000"]

在 JSON 数组元素和 JSON 对象键值中允许嵌套:

[99, {
    
    "id": "HK500", "cost": 75.99}, ["hot", "cold"]]
{
    
    "k1": "value", "k2": [10, 20]}

您还可以从 MySQL 为此目的提供的许多函数中获取 JSON 值(请参阅 第 12.18.2 节,“创建 JSON 值的函数”)以及将其他类型的值使用 CAST(value AS JSON) (请参阅 JSON 之间的转换)和非 JSON 值)转换为JSON类型 。接下来的几段描述了 MySQL 如何处理作为输入提供的 JSON 值。

在 MySQL 中,JSON 值被写为字符串。MySQL 解析在需要 JSON 值的上下文中使用的任何字符串,如果它作为 JSON 无效,则会产生错误。这些上下文包括将值插入到具有 JSON数据类型的列中,并将参数传递给需要 JSON 值的函数(通常显示为 *json_doc*或 *json_val*在 MySQL JSON 函数的文档中显示),如以下示例所示:

  • 如果值是有效的 JSON 值,则尝试将值插入JSON 列能成功,但如果不是,则失败:
mysql> CREATE TABLE t1 (jdoc JSON);
Query OK, 0 rows affected (0.20 sec)

mysql> INSERT INTO t1 VALUES('{"key1": "value1", "key2": "value2"}');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO t1 VALUES('[1, 2,');
ERROR 3140 (22032) at line 2: Invalid JSON text: 
"Invalid value." at position 6 in value (or column) '[1, 2,'.

In solchen Fehlermeldungen Nist die Position „an Position“ 0-basiert, dies sollte jedoch nur als grober Hinweis darauf angesehen werden, wo im Wert das Problem tatsächlich auftritt.

  • Die JSON_TYPE()Funktion erwartet einen JSON-Parameter und versucht, ihn in einen JSON-Wert zu analysieren. Wenn gültig, wird ein JSON-Typwert zurückgegeben, andernfalls wird ein Fehler generiert:

    mysql> SELECT JSON_TYPE('["a", "b", 1]');
    +----------------------------+
    | JSON_TYPE('["a", "b", 1]') |
    +----------------------------+
    | ARRAY                      |
    +----------------------------+
    
    mysql> select json_type('{}');
    +-----------------+
    | json_type('{}') |
    +-----------------+
    | OBJECT          |
    +-----------------+
    1 row in set (0.00 sec)
    
    mysql> SELECT JSON_TYPE('"hello"');
    +----------------------+
    | JSON_TYPE('"hello"') |
    +----------------------+
    | STRING               |
    +----------------------+
    
    mysql> SELECT JSON_TYPE('hello');
    ERROR 3146 (22032): Invalid data type for JSON data in argument 1
    to function json_type; a JSON string or JSON type is required.
    

    MySQL verwendet utf8mb4Regeln für den Zeichensatz (Zeichensatz) und utf8mb4_bindie Zeichenreihenfolge (Sortierung, Zeichensortierregeln, Bin bedeutet, dass codierte Werte zum Vergleich verwendet werden), um im JSON-Kontext verwendete Zeichenfolgen zu verarbeiten. Zeichenfolgen in anderen Zeichensätzen werden utf8mb4nach Bedarf konvertiert. (Für Zeichenfolgen im Zeichensatz asciioder utf8ist keine Konvertierung erforderlich, da asciiund eine Teilmenge von utf8ist .)utf8mb4

Beschreibung (fügen Sie Ihre eigene hinzu)

Sortierung, Sortierregeln für Zeichen. _binZeigt an, dass zum Vergleich codierte Werte (binär) verwendet werden, _ciwas darauf hinweist, _csdass die Groß-/Kleinschreibung nicht beachtet wird

Sie können auch angeben, ob beim Wert der Zeichenfolge die Groß-/Kleinschreibung beachtet werden soll, was sich von der Frage unterscheidet, ob beim Tabellennamen von MySQL die Groß-/Kleinschreibung beachtet werden soll.

CREATE TABLE `t` (
  `id` int(11) DEFAULT NULL,
  `s1` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `s2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

# 插入两个数据,一个大写的Sql,一个小写的sql
mysql> insert into t values (NULL,'Sql','Sql'), (NULL,'sql','sql');
Query OK, 2 rows affected (0.04 sec)

# 查询所有数据:只有两条数据
mysql> select * from t;
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  1 | Sql  | Sql  |
|  2 | sql  | sql  |
+----+------+------+
2 rows in set (0.00 sec)

# 查询 _bin 编码值的字段,这是区分大小写的,所以只能得到小写sql的那一条数据
mysql> select * from t where s1 = 'sql';
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  2 | sql  | sql  |
+----+------+------+
1 row in set (0.00 sec)

# 查询 _ci 不区分大小写的字段,所以能查询到大写的Sql和小写的sql,共两条数据
mysql> select * from t where s2 = 'sql';
+----+------+------+
| id | s1   | s2   |
+----+------+------+
|  1 | Sql  | Sql  |
|  2 | sql  | sql  |
+----+------+------+
2 rows in set (0.00 sec)

Alternativ zum Schreiben von JSON-Werten mithilfe von Literalzeichenfolgen gibt es Funktionen zum Kombinieren von JSON-Werten aus Komponentenelementen. JSON_ARRAY()Akzeptiert eine (möglicherweise leere) Liste von Werten und gibt ein JSON-Array zurück, das diese Werte enthält:

mysql> SELECT JSON_ARRAY('a', 1, NOW());
+----------------------------------------+
| JSON_ARRAY('a', 1, NOW())              |
+----------------------------------------+
| ["a", 1, "2015-07-27 09:43:47.000000"] |
+----------------------------------------+

JSON_OBJECT()Ruft eine (möglicherweise leere) Liste von Schlüssel-Wert-Paaren ab und gibt ein JSON-Objekt zurück, das diese Paare enthält:

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc');
+---------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc') |
+---------------------------------------+
| {
   
   "key1": 1, "key2": "abc"}            |
+---------------------------------------+

JSON_MERGE()Akzeptiert zwei oder mehr JSON-Dokumente und gibt das kombinierte Ergebnis zurück:

mysql> SELECT JSON_MERGE('["a", 1]', '{"key": "value"}');
+--------------------------------------------+
| JSON_MERGE('["a", 1]', '{"key": "value"}') |
+--------------------------------------------+
| ["a", 1, {
   
   "key": "value"}]                 |
+--------------------------------------------+

Informationen zu Zusammenführungsregeln finden Sie unter Normalisierung, Zusammenführung und automatisches Umschließen von JSON-Werten .

JSON-Werte können benutzerdefinierten Variablen zugewiesen werden:

mysql> SET @j = JSON_OBJECT('key', 'value');
mysql> SELECT @j;
+------------------+
| @j               |
+------------------+
| {
   
   "key": "value"} |
+------------------+

# 以下为我自己的测试。结论:@j的类型是longtext,而不是json类型
mysql> create table test select @j;
Query OK, 1 row affected (0.09 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> desc test;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| @j    | longtext | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
1 row in set (0.03 sec)

Allerdings kann eine benutzerdefinierte Variable kein JSONDatentyp sein. Obwohl sie @jim vorherigen Beispiel wie ein JSON-Wert aussieht und den gleichen Zeichensatz und die gleiche Sortierung wie ein JSON-Wert hat, hat sie keinen Datentyp JSON. Stattdessen JSON_OBJECT()wird das Ergebnis in eine Zeichenfolge umgewandelt, wenn es einer Variablen zugewiesen wird (ich habe es tatsächlich gemessen, um es in einen Typ umzuwandeln longtext).

Die durch die Konvertierung eines JSON-Werts generierte Zeichenfolge verfügt über einen Zeichensatz utf8mb4und eine Sortierung utf8mb4_bin:

mysql> SELECT CHARSET(@j), COLLATION(@j);
+-------------+---------------+
| CHARSET(@j) | COLLATION(@j) |
+-------------+---------------+
| utf8mb4     | utf8mb4_bin   |
+-------------+---------------+

Da utf8mb4_bines sich um eine binäre Sortierung handelt, wird beim Vergleich von JSON-Werten die Groß-/Kleinschreibung beachtet.

# json字段区分大小写,但普通的字符串字段是不区分大小写
mysql> SELECT JSON_ARRAY('x') = JSON_ARRAY('X'), 'x' = 'X';
+-----------------------------------+-----------+
| JSON_ARRAY('x') = JSON_ARRAY('X') | 'x' = 'X' |
+-----------------------------------+-----------+
|                                 0 |         1 |
+-----------------------------------+-----------+
1 row in set (0.00 sec)

Die Groß-/Kleinschreibung gilt auch für JSON- nullund true-Zeichen false, die immer in Kleinbuchstaben geschrieben werden müssen:

mysql> SELECT JSON_VALID('null'), JSON_VALID('Null'), JSON_VALID('NULL');
+--------------------+--------------------+--------------------+
| JSON_VALID('null') | JSON_VALID('Null') | JSON_VALID('NULL') |
+--------------------+--------------------+--------------------+
|                  1 |                  0 |                  0 |
+--------------------+--------------------+--------------------+

mysql> SELECT CAST('null' AS JSON);
+----------------------+
| CAST('null' AS JSON) |
+----------------------+
| null                 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT CAST('NULL' AS JSON);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json:
"Invalid value." at position 0 in 'NULL'.

Die Groß-/Kleinschreibung von JSON-Zeichen unterscheidet sich von der Groß-/Kleinschreibung von SQL NULLund TRUEZeichen FALSE, bei denen es sich um beliebige Buchstaben handeln kann:

mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL);
+--------------+--------------+--------------+
| ISNULL(null) | ISNULL(Null) | ISNULL(NULL) |
+--------------+--------------+--------------+
|            1 |            1 |            1 |
+--------------+--------------+--------------+

Manchmal kann es notwendig oder wünschenswert sein, Anführungszeichen (doppelte "oder einfache Anführungszeichen ') in ein JSON-Dokument einzufügen. Nehmen Sie für dieses Beispiel an, dass Sie einige JSON-Objekte in eine Tabelle einfügen möchten, die mit den hier gezeigten SQL-Anweisungen erstellt wurde. Diese enthalten Zeichenfolgen, die die Anweisungen darstellen, die einige praktische Fakten über MySQL darstellen, die jeweils für die entsprechende Schlüsselwortpaarung von Zeichenfolgen relevant sind:

mysql> CREATE TABLE facts (sentence JSON);

# 假设要插入json:mascot: The MySQL mascot is a dolphin named "Sakila".
# 使用 MySQL函数 JSON_OBJECT() 将其作为 JSON 对象插入到 facts 表中,必须使用反斜杠转义每个引号字符:
mysql> INSERT INTO facts VALUES
     >   (JSON_OBJECT("mascot", "Our mascot is a dolphin named \"Sakila\"."));

# 如果您将值作为 JSON 对象文字插入,则这不会以相同的方式工作,在这种情况下,您必须使用双反斜杠转义序列,如下所示:
mysql> INSERT INTO facts VALUES
     >   ('{"mascot": "Our mascot is a dolphin named \\"Sakila\\"."}');

# 使用双反斜杠可以防止 MySQL 执行转义序列处理,而是使其将字符串文字传递给存储引擎进行处理。在以刚才显示的任何一种方式插入 JSON 对象后,您可以通过执行简单的 SELECT 来看到反斜杠出现在 JSON 列值中,如下所示:
mysql> SELECT sentence FROM facts;
+---------------------------------------------------------+
| sentence                                                |
+---------------------------------------------------------+
| {
   
   "mascot": "Our mascot is a dolphin named \"Sakila\"."} |
+---------------------------------------------------------+

Um diesen mascotspeziellen Satz zu finden, der als Schlüssel verwendet wird, können Sie den Spaltenpfadoperator ->wie folgt verwenden:

mysql> SELECT sentence->"$.mascot" FROM facts;
+---------------------------------------------+
| sentence->"$.mascot"                        |
+---------------------------------------------+
| "Our mascot is a dolphin named \"Sakila\"." |
+---------------------------------------------+
1 row in set (0.00 sec)

Dadurch bleiben der Backslash und die umgebenden Anführungszeichen erhalten. Um den gewünschten Wert als Schlüssel anzuzeigen mascot, jedoch ohne umgebende Anführungszeichen oder Escape-Zeichen, verwenden Sie den Inline-Pfadoperator ->>wie folgt:

mysql> SELECT sentence->>"$.mascot" FROM facts;
+-----------------------------------------+
| sentence->>"$.mascot"                   |
+-----------------------------------------+
| Our mascot is a dolphin named "Sakila". |
+-----------------------------------------+

# 我实测报错:
mysql> SELECT sentence->>"$.mascot" FROM facts;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '>"$.mascot" FROM facts' at line 1

Anmerkungen

Wenn der Server-SQL-Modus aktiviert ist NO_BACKSLASH_ESCAPES, funktioniert das vorherige Beispiel nicht ordnungsgemäß. Wenn dieser Modus festgelegt ist, können JSON-Objektliterale mit einem einzelnen Backslash anstelle eines doppelten Backslashs eingefügt werden, und die Backslashes bleiben erhalten. Wenn JSON_OBJECT()Sie diese Funktion beim Durchführen einer Einfügung verwenden und dieser Modus festgelegt ist, müssen Sie einfache und doppelte Anführungszeichen wie folgt abwechseln:

mysql> INSERT INTO facts VALUES
     > (JSON_OBJECT('mascot', 'Our mascot is a dolphin named "Sakila".'));

Weitere Informationen zur Auswirkung dieses Modus auf maskierte Zeichen in JSON-Werten finden Sie in JSON_UNQUOTE()der Funktionsbeschreibung.

5.2. Standardisierung, Zusammenführung und automatische Verpackung von JSON-Werten

5.2.1. Normalisierte JSON-Werte

Wenn eine Zeichenfolge analysiert und als gültiges JSON-Dokument befunden wird, wird sie auch normalisiert: Mitglieder mit Schlüsseln, die Duplikate von Schlüsseln sind, die zuvor im Dokument gefunden wurden, werden verworfen (auch wenn die Werte unterschiedlich sind). Der durch den folgenden JSON_OBJECT()Aufruf generierte Objektwert enthält nicht das zweite key1Element, da der Schlüssel vor dem Wert erscheint:

mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def');
+------------------------------------------------------+
| JSON_OBJECT('key1', 1, 'key2', 'abc', 'key1', 'def') |
+------------------------------------------------------+
| {
   
   "key1": 1, "key2": "abc"}                           |
+------------------------------------------------------+

Beachten

Diese „First Key Wins“-Behandlung doppelter Schlüssel steht im Widerspruch zu RFC 7159 . Dies ist ein bekanntes Problem in MySQL 5.7 und wurde in MySQL 8.0 behoben. (Fehler Nr. 86866, Fehler Nr. 26369555)

MySQL verwirft außerdem zusätzliche Leerzeichen zwischen Schlüsseln, Werten oder Elementen im ursprünglichen JSON-Dokument und lässt bei der Anzeige nach jedem Komma ( ,) oder Doppelpunkt ( ) :ein Leerzeichen (oder fügt es bei Bedarf ein ). Dies geschieht zur Verbesserung der Lesbarkeit.

MySQL-Funktionen, die JSON-Werte erzeugen (siehe Abschnitt 12.18.2, „Funktionen, die JSON-Werte erstellen“ ), geben immer normalisierte Werte zurück.

Um die Sucheffizienz zu verbessern, werden auch die Schlüssel von JSON-Objekten sortiert. Sie sollten sich darüber im Klaren sein, dass sich die Ergebnisse dieser Sortierung ändern können und es nicht garantiert werden kann, dass sie über alle Versionen hinweg konsistent sind .

5.2.2. JSON-Werte zusammenführen

Im Zusammenhang mit der Kombination mehrerer Arrays werden mehrere Arrays zu einem einzigen Array zusammengefasst, indem das nachfolgend benannte Array mit dem Ende des ersten Arrays verkettet wird . Im folgenden Beispiel JSON_MERGE()werden seine Parameter in einem Array zusammengefasst:

mysql> SELECT JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]');
+-----------------------------------------------------+
| JSON_MERGE('[1, 2]', '["a", "b"]', '[true, false]') |
+-----------------------------------------------------+
| [1, 2, "a", "b", true, false]                       |
+-----------------------------------------------------+

Die Zusammenführung erfolgt auch beim Einfügen von Werten in JSON-Spalten, wie unten gezeigt:

mysql> CREATE TABLE t1 (c1 JSON);

mysql> INSERT INTO t1 VALUES
     >     ('{"x": 17, "x": "red"}'),
     >     ('{"x": 17, "x": "red", "x": [3, 5, 7]}');

mysql> SELECT c1 FROM t1;
+-----------+
| c1        |
+-----------+
| {
   
   "x": 17} |
| {
   
   "x": 17} |
+-----------+

Wenn mehrere Objekte kombiniert werden, entsteht ein Objekt. Wenn mehrere Objekte denselben Schlüssel haben, ist der Wert für diesen Schlüssel im resultierenden zusammengeführten Objekt ein Array, das den Wert des Schlüssels enthält:

mysql> SELECT JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}');
+----------------------------------------------------+
| JSON_MERGE('{"a": 1, "b": 2}', '{"c": 3, "a": 4}') |
+----------------------------------------------------+
| {
   
   "a": [1, 4], "b": 2, "c": 3}                      |
+----------------------------------------------------+

5.2.3. JSON-Werte automatisch umschließen

  • Automatisches Umbrechen von Nicht-Array-Werten

Nicht-Array-Werte, die in Kontexten verwendet werden, die Array-Werte erfordern, werden automatisch umbrochen : Der Wert wird von [und- ]Zeichen umgeben, um ihn in ein Array umzuwandeln. In den folgenden Anweisungen wird jedes Argument automatisch als Array ( [1], [2]) verpackt. Kombinieren Sie sie dann, um ein einziges resultierendes Array zu erzeugen:

mysql> SELECT JSON_MERGE('1', '2'); # -> 临时状态: JSON_MERGE([1], [2])
+----------------------+
| JSON_MERGE('1', '2') |
+----------------------+
| [1, 2]               |
+----------------------+
  • Automatische Objektverpackung

Führen Sie Array- und Objektwerte zusammen, indem Sie das Objekt automatisch in ein Array einschließen und die beiden Arrays zusammenführen:

mysql> SELECT JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}');
# -> 临时状态:JSON_MERGE('[10, 20]', '[{"a": "x", "b": "y"}]'); 将后面的{} 自动包装为[{}]
+------------------------------------------------+
| JSON_MERGE('[10, 20]', '{"a": "x", "b": "y"}') |
+------------------------------------------------+
| [10, 20, {
   
   "a": "x", "b": "y"}]                 |
+------------------------------------------------+

5.3. JSON-Werte suchen und ändern

JSON-Pfadausdrücke wählen einen Wert in einem JSON-Dokument aus.

Pfadausdrücke sind nützlich für Funktionen, die einen Teil eines JSON-Dokuments extrahieren oder ein JSON-Dokument ändern, um anzugeben, wo im Dokument gearbeitet werden soll. nameDie folgende Abfrage extrahiert beispielsweise den Wert eines Mitglieds mit einem Schlüssel aus einem JSON-Dokument :

mysql> SELECT JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name');
+---------------------------------------------------------+
| JSON_EXTRACT('{"id": 14, "name": "Aztalan"}', '$.name') |
+---------------------------------------------------------+
| "Aztalan"                                               |
+---------------------------------------------------------+

Die Pfadsyntax verwendet ein führendes $Zeichen, um das betrachtete JSON-Dokument zu identifizieren, gefolgt von optionalen Ausdrücken nach dem Selektor, die wiederum spezifischere Teile des Dokuments angeben:

  • Ein Punkt, gefolgt vom Schlüsselnamen, benennt das Mitglied im Objekt, das den angegebenen Schlüssel verwendet. Wenn der Name ohne Anführungszeichen in einem Pfadausdruck nicht zulässig ist (er enthält beispielsweise Leerzeichen), muss der Schlüsselname in doppelten Anführungszeichen angegeben werden.

  • [N]Unmittelbar darauf pathfolgt die Auswahl eines Elements pathmit dem Index des Array-Namens ( ) , bei dem es sich um eine Ganzzahl handelt, die bei Null beginnt. Wenn die Auswahl kein Array ist, ist * *[0] äquivalent zu :NNpathpathpath

    mysql> SELECT JSON_SET('"x"', '$[0]', 'a');
    +------------------------------+
    | JSON_SET('"x"', '$[0]', 'a') |
    +------------------------------+
    | "a"                          |
    +------------------------------+
    1 row in set (0.00 sec)
    
  • Der Pfad kann *Platzhalterzeichen enthalten **:

    • .[*]Berechnen Sie die Werte aller Mitglieder in einem JSON-Objekt.
    • [*]Berechnen Sie den Wert aller Elemente in einem JSON-Array.
    • prefix**suffixZählt alle Pfade, prefixdie mit beginnen und enden.suffix
  • Pfade, die im Dokument nicht vorhanden sind (als nicht vorhandene Daten ausgewertet werden), werden als ausgewertet NULL.

Lassen Sie uns $auf dieses JSON-Array mit drei Elementen verweisen:

[3, {
    
    "a": [5, 6], "b": 10}, [99, 100]]

Dann:

  • $[0]Bewertet als 3.
  • $[1]Bewertet als {"a": [5, 6], "b": 10}.
  • $[2]Bewertet als [99, 100].
  • $[3]Wird ausgewertet als NULL(bezieht sich auf das vierte Array-Element, das nicht existiert).

Da $[1]sie $[2]zu nichtskalaren Werten ausgewertet werden, können sie als Grundlage für spezifischere Pfadausdrücke verwendet werden, die verschachtelte Werte auswählen. Beispiel:

  • $[1].aBewertet als [5, 6].
  • $[1].a[1]Bewertet als 6.
  • $[1].bBewertet als 10.
  • $[2][0]Bewertet als 99.

Wie bereits erwähnt, müssen die Pfadkomponenten des Schlüssels in Anführungszeichen gesetzt werden, wenn der Schlüsselname in einem Pfadausdruck nicht zulässig ist. Beziehen wir $uns auf diesen Wert:

{
    
    "a fish": "shark", "a bird": "sparrow"}

Beide Schlüssel enthalten ein Leerzeichen und müssen in Anführungszeichen gesetzt werden:

  • $."a fish"Bewertet als shark.
  • $."a bird"Bewertet als sparrow.

Ein Pfad, der Platzhalter verwendet, ergibt ein Array, das mehrere Werte enthalten kann:

mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.*') |
+---------------------------------------------------------+
| [1, 2, [3, 4, 5]]                                       |
+---------------------------------------------------------+
mysql> SELECT JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]'); # 与'$.c' 等价
+------------------------------------------------------------+
| JSON_EXTRACT('{"a": 1, "b": 2, "c": [3, 4, 5]}', '$.c[*]') |
+------------------------------------------------------------+
| [3, 4, 5]                                                  |
+------------------------------------------------------------+

Im folgenden Beispiel ergibt path $**.bmehrere Pfade ( $.a.bsum $.c.b) und erzeugt ein Array übereinstimmender Pfadwerte:

mysql> SELECT JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b');
+---------------------------------------------------------+
| JSON_EXTRACT('{"a": {"b": 1}, "c": {"b": 2}}', '$**.b') |
+---------------------------------------------------------+
| [1, 2]                                                  |
+---------------------------------------------------------+

column->pathIn MySQL 5.7.9 und höher können Sie JSON-Spaltenbezeichner und JSON-Pfadausdrücke als Synonyme für verwenden JSON_EXTRACT(column, path). Weitere Informationen finden Sie in Abschnitt 12.18.3, „Funktionen zum Durchsuchen von JSON-Werten“ . Siehe auch Generierte Spalten indizieren, um JSON-Spaltenindizes bereitzustellen .

Einige Funktionen nehmen ein vorhandenes JSON-Dokument, ändern es auf irgendeine Weise und geben das geänderte Dokument als Ergebnis zurück. Pfadausdrücke geben an, wo im Dokument Änderungen vorgenommen werden. Beispielsweise akzeptieren JSON_SET()die Funktionen , JSON_INSERT()und JSON_REPLACE()jeweils ein JSON-Dokument sowie ein oder mehrere Pfad/Wert-Paare, die beschreiben, wo das Dokument geändert werden soll und welche Werte verwendet werden sollen. Diese Funktionen unterscheiden sich darin, wie sie mit vorhandenen und nicht vorhandenen Werten im Dokument umgehen.

Betrachten Sie dieses Dokument:

mysql> SET @j = '["a", {"b": [true, false]}, [10, 20]]';

JSON_SET()Ersetzen Sie den Wert eines vorhandenen Pfads und fügen Sie den Wert eines nicht vorhandenen Pfads hinzu:

mysql> SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+--------------------------------------------+
| JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+--------------------------------------------+
| ["a", {
   
   "b": [1, false]}, [10, 20, 2]]      |
+--------------------------------------------+

In diesem Fall wählt der Pfad $[1].b[0]einen vorhandenen Wert ( true), der durch den folgenden Pfadparameterwert ( 1) ersetzt wird. Der Pfad $[2][2]ist nicht vorhanden, daher wird der entsprechende Wert ( ) zu den ausgewählten Werten 2hinzugefügt .$[2]

JSON_INSERT()Fügen Sie neue Werte hinzu, ohne vorhandene Werte zu ersetzen:

mysql> SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+-----------------------------------------------+
| JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+-----------------------------------------------+
| ["a", {
   
   "b": [true, false]}, [10, 20, 2]]      |
+-----------------------------------------------+
# TODO: 没看明白,为什么 '$[1].b[0]', 1 这个路径/值 对没有被添加到"b"数组的0号下标中

JSON_REPLACE()Ersetzen Sie vorhandene Werte und ignorieren Sie neue Werte:

mysql> SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+------------------------------------------------+
| JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+------------------------------------------------+
| ["a", {
   
   "b": [1, false]}, [10, 20]]             |
+------------------------------------------------+

Pfad/Wert-Paare werden von links nach rechts ausgewertet. Das durch die Auswertung eines Paares erzeugte Dokument wird zum neuen Wert für die Auswertung des nächsten Paares.

JSON_REMOVE()Akzeptiert ein JSON-Dokument und einen (oder mehrere) Pfade, die die aus dem Dokument zu entfernenden Werte angeben. Der Rückgabewert ist das Originaldokument abzüglich aller im Dokument vorhandenen Pfadauswahlen:

mysql> SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]');
+---------------------------------------------------+
| JSON_REMOVE(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') |
+---------------------------------------------------+
| ["a", {
   
   "b": [true]}]                              |
+---------------------------------------------------+

Pfade haben folgende Auswirkungen:

  • $[2]Passen Sie es an [10, 20]und löschen Sie es.
  • Der erste stimmt mit dem Element $[1].b[1]überein und entfernt es.bfalse
  • Das zweite Element $[1].b[1]stimmt mit keinem Element überein: Das erwartete Element wurde entfernt, der Pfad existiert nicht mehr und hat keine Auswirkung.

5.4、JSON 路径语法

MySQL 支持并在本手册其他地方描述的许多 JSON 函数(请参阅第 12.18 节,“JSON 函数”)需要路径表达式来标识 JSON 文档中的特定元素。路径由路径的范围和一个或多个路径分支组成。对于 MySQL JSON 函数中使用的路径,范围始终是正在搜索或以其他方式操作的文档,由前导 $字符表示。路径分支(路径腿)由句点字符 ( .) 分隔。数组中的单元格由 [N] 表示 ,其中 N 是一个非负整数。键名必须是双引号字符串或有效的 ECMAScript 标识符(请参阅 http://www.ecma-international.org/ecma-262/5.1/#sec-7.6)。路径表达式(如 JSON 文本)应使用 asciiutf8utf8mb4字符集进行编码。其他字符编码被隐式强制转换为utf8mb4. 完整的语法如下所示:

pathExpression:
    scope[(pathLeg)*]

pathLeg:
    member | arrayLocation | doubleAsterisk

member:
    period ( keyName | asterisk )

arrayLocation:
    leftBracket ( nonNegativeInteger | asterisk ) rightBracket

keyName:
    ESIdentifier | doubleQuotedString

doubleAsterisk:
    '**'

period:
    '.'

asterisk:
    '*'

leftBracket:
    '['

rightBracket:
    ']'

如前所述,在 MySQL 中,路径的范围始终是正在操作的文档,表示为 $. 您可以'$'在 JSON 路径表达式中用作文档的同义词。

笔记

一些实现支持 JSON 路径范围的列引用;目前,MySQL 不支持这些。

通配符*** 标记的使用如下:

  • .*表示对象中所有成员的值。

  • [*]表示数组中所有单元格的值。

  • [prefix]**suffix 表示以 prefix 开头和 suffix 结尾的所有路径。 prefix 是可选的,但 suffix 是必需的;换句话说,路径不可能以 ** 结尾。

    Darüber hinaus enthält der Pfad möglicherweise nicht die Sequenz ***(3 Sternchen).

Beispiele für die Pfadsyntax finden Sie in den Beschreibungen verschiedener JSON-Funktionen, die Pfade als Argumente verwenden, z. B. JSON_CONTAINS_PATH(), JSON_SET()und JSON_REPLACE(). Ein Beispiel für die Verwendung * der Platzhalterzeichen und **finden Sie in der Funktionsbeschreibung JSON_SEARCH().

5.5. Vergleich und Sortierung von JSON-Werten

Sie können JSON-Werte mit =den Operatoren , <, <=, >, >=, und vergleichen <>.!=<=>

Die folgenden Vergleichsoperatoren und Funktionen werden für JSON-Werte noch nicht unterstützt:

Die Problemumgehung für die gerade aufgeführten Vergleichsoperatoren und -funktionen besteht darin, die JSON-Werte in native MySQL-Zahlen- oder String-Datentypen zu konvertieren, sodass sie über konsistente Nicht-JSON-Skalartypen verfügen.

Der Vergleich der JSON-Werte erfolgt auf zwei Ebenen. Der Vergleich der ersten Ebene basiert auf dem JSON-Typ des verglichenen Werts. Wenn die Typen unterschiedlich sind, hängt das Ergebnis des Vergleichs nur davon ab, welcher Typ die höhere Priorität hat. Wenn zwei Werte denselben JSON-Typ haben, wird ein Vergleich der zweiten Ebene mithilfe typspezifischer Regeln durchgeführt.

Die folgende Liste zeigt die Priorität der JSON-Typen, von der höchsten bis zur niedrigsten Priorität. (Der Typname ist JSON_TYPE()der von der Funktion zurückgegebene Name.) Typen, die zusammen in einer Zeile erscheinen, haben die gleiche Priorität. Jeder zuvor in der Liste aufgeführte Wert vom Typ JSON ist größer als jeder später in der Liste aufgeführte Wert vom Typ JSON.

BLOB
BIT
OPAQUE
DATETIME
TIME
DATE
BOOLEAN
ARRAY
OBJECT
STRING
INTEGER, DOUBLE
NULL

Für JSON-Werte derselben Priorität sind die Vergleichsregeln typspezifisch:

  • BLOB

    NVergleicht die ersten Bytes zweier Werte , wobei Ndie Anzahl der Bytes im kürzeren Wert angegeben ist. Wenn die ersten NBytes zweier Werte gleich sind, wird der kürzere Wert vor dem längeren Wert sortiert.

  • BIT

    BLOBGleiche Regeln wie .

  • OPAQUE

    BLOBGleiche Regeln wie . OPAQUETyp ist ein nicht klassifizierter Typ.

  • DATETIME

    Werte aus früheren Zeitpunkten werden vor Werten sortiert, die spätere Zeitpunkte darstellen. Zwei Werte sind gleich, wenn sie ursprünglich aus MySQL stammen DATETIMEbzw. TIMESTAMPden gleichen Zeitpunkt repräsentieren.

  • TIME

    Der kleinere der beiden Zeitwerte wird vor dem größeren sortiert.

  • DATE

    Ältere Daten werden vor späteren Daten sortiert.

  • ARRAY

    Zwei JSON-Arrays sind gleich, wenn sie die gleiche Länge haben und die Werte an entsprechenden Positionen im Array gleich sind.

    Wenn die Arrays nicht gleich sind, wird ihre Reihenfolge durch das erste Element an der Position bestimmt, an der der Unterschied besteht. Arrays mit kleineren Werten an dieser Position werden zuerst sortiert. Wenn alle Werte des kürzeren Arrays gleich den entsprechenden Werten im längeren Array sind, wird das kürzere Array zuerst sortiert.

    Beispiel:

    [] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]
    
  • BOOLEAN

    Die falschen Zeichen von JSON sind kleiner als die wahren Zeichen von JSON.

  • OBJEKT

    Zwei JSON-Objekte sind gleich, wenn sie über denselben Schlüsselsatz verfügen und jeder Schlüssel in beiden Objekten denselben Wert hat.

    Beispiel:

    {"a": 1, "b": 2} = {"b": 2, "a": 1}
    

    Die Reihenfolge zweier ungleicher Objekte ist nicht spezifiziert, aber deterministisch. (Hinweis: Ich verstehe diesen Satz nicht)

  • STRING

    Zeichenfolgen werden lexikalisch nach den ersten Bytes sortiert, die in den beiden zu vergleichenden Zeichenfolgen utf8mb4codiert sind , wobei die Länge der kürzeren Zeichenfolge angegeben ist. Wenn die ersten Bytes zweier Strings gleich sind, gilt der kürzere String als kleiner als der längere String.NNN

    Beispiel:

    "a" < "ab" < "b" < "bc"
    

    Diese Sortierung entspricht der Verwendung utf8mb4_binder Sortierung zum Sortieren von SQL-Zeichenfolgen. Aufgrund utf8mb4_binder binären Sortierung wird beim Vergleich von JSON-Werten die Groß-/Kleinschreibung beachtet:

    "A" < "a"
    
  • INTEGER,DOUBLE

    JSON-Werte können genaue und ungefähre Zahlen enthalten. Eine allgemeine Diskussion dieser Zahlentypen finden Sie in Abschnitt 9.1.2, „Zahlenliterale“ .

    Die Regeln zum Vergleich nativer numerischer MySQL-Typen werden in Abschnitt 12.3, „Typkonvertierungen in der Ausdrucksauswertung“ erläutert , die Regeln zum Vergleich numerischer Typen in JSON-Werten unterscheiden sich jedoch etwas:

    • Bei Vergleichen zwischen zwei Spalten unter Verwendung nativer MySQL- INTbzw. DOUBLEnumerischer Typen ist bekannt, dass alle Vergleiche Ganzzahlen und Doppelzahlen umfassen, sodass für alle Zeilen Ganzzahlen in Doppelzahlen umgewandelt werden. Das heißt, eine genaue Zahl in eine ungefähre Zahl umwandeln.

    • Wenn eine Abfrage hingegen zwei JSON-Spalten mit Zahlen vergleicht, kann sie nicht im Voraus wissen, ob es sich bei den Zahlen um Ganzzahlen oder Doppelzahlen handelt. Um ein möglichst konsistentes Verhalten über alle Zeilen hinweg zu gewährleisten, wandelt MySQL ungefähre Zahlen in exakte Zahlen um. Die resultierende Reihenfolge ist konsistent und verliert nicht die Genauigkeit exakter Wertzahlen. Bei den Skalaren 9223372036854775805, 9223372036854775806, 9223372036854775807 und 9.223372036854776e18 lautet die Reihenfolge beispielsweise wie folgt:

    9223372036854775805 < 9223372036854775806 < 9223372036854775807
    < 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001
    

    Wenn der JSON-Vergleich numerische Nicht-JSON-Vergleichsregeln verwendet, kann es zu einer inkonsistenten Reihenfolge kommen. Gängige MySQL-Zahlenvergleichsregeln ergeben die folgende Reihenfolge:

    • Ganzzahlvergleich:

      9223372036854775805 < 9223372036854775806 < 9223372036854775807
      

      (undefiniert 9.223372036854776e18)

    • Doppelter Vergleich:

      9223372036854775805 = 9223372036854775806 = 9223372036854775807 = 9.223372036854776e18
      

Bei jedem NULLVergleich von JSON-Werten mit SQL lautet das Ergebnis UNKNOWN.

Für Vergleiche von JSON- und Nicht-JSON-Werten werden Nicht-JSON-Werte gemäß den Regeln in der folgenden Tabelle in JSON konvertiert und anschließend werden die Werte wie zuvor beschrieben verglichen.

5.6. Konvertieren zwischen JSON- und Nicht-JSON-Werten

Die folgende Tabelle fasst die Regeln zusammen, die MySQL bei der Konvertierung zwischen JSON-Werten und anderen Werttypen befolgt:

Tabelle 11.3 JSON-Konvertierungsregeln

Andere Arten CAST (andere Typen als JSON) CAST(JSON AS andere Typen)
JSON Unverändert Unverändert
utf8-Zeichentyp ( utf8mb4, utf8, ascii) Die Zeichenfolge wird in einen JSON-Wert geparst. JSON-Werte werden in Strings serialisiert utf8mb4.
Andere Charaktertypen Andere Zeichenkodierungen werden implizit in utf8mb4Zeichentypen konvertiert und entsprechend dem utf8-Zeichensatz verarbeitet. JSON-Werte werden in utf8mb4Strings serialisiert und dann in andere Zeichenkodierungen konvertiert. Die Ergebnisse sind möglicherweise nicht sinnvoll.
NULL NULLGibt einen JSON-Wert vom Typ zurück . unzutreffend.
GEO-Typ ST_AsGeoJSON()Konvertieren Sie GEO-Werte in JSON-Dokumente , indem Sie aufrufen . Illegale Operation. Lösung: Übergeben Sie CAST(json_val AS CHAR)das Ergebnis von, um ST_GeomFromGeoJSON()das Ergebnis von an zu übergeben ST_GeomFromGeoJSON().
Alle anderen Typen Erzeugt ein JSON-Dokument, das aus einem einzelnen Skalarwert besteht. Erfolgreich, wenn das JSON-Dokument einen einzelnen Skalarwert des Zieltyps enthält und der Skalarwert in den Zieltyp konvertiert werden kann. Andernfalls kehren Sie zurück NULLund generieren Sie eine Warnung.

Für JSON-Werte ORDER BYund GROUP BYfunktioniert nach folgenden Prinzipien:

  • Skalare JSON-Werte werden nach denselben Regeln wie in der vorherigen Diskussion sortiert.
  • Bei der aufsteigenden Sortierung werden SQLs NULLvor allen JSON-Werten, einschließlich JSON-NULL-Literalen, sortiert; bei absteigender Sortierung werden SQLs NULLnach allen JSON-Werten, einschließlich JSON-NULL-Literalen, sortiert.
  • Der Sortierschlüssel eines JSON-Werts wird durch max_sort_lengthden Wert einer Systemvariablen eingeschränkt max_sort_lengthund gilt daher als gleich, wenn die ersten Bytes gleich sind (und sich nur dann unterscheiden).
  • Das Sortieren nichtskalarer Werte wird derzeit nicht unterstützt und es wird eine Warnung angezeigt.

Für die Sortierung kann es von Vorteil sein, den JSON-Skalar in einen anderen nativen MySQL-Typ zu konvertieren. Wenn beispielsweise jdoceine benannte Spalte ein JSON-Objekt enthält, dessen Mitglieder idaus Schlüsseln und nicht negativen Werten bestehen, verwenden Sie diesen Ausdruck, um idnach Wert zu sortieren:

ORDER BY CAST(JSON_EXTRACT(jdoc, '$.id') AS UNSIGNED)

Wenn zufällig eine generierte Spalte vorhanden ist, die mit ORDER BYdemselben Ausdruck wie in definiert ist, erkennt der MySQL-Optimierer dies und berücksichtigt den Index zur Verwendung im Abfrageausführungsplan. Siehe Abschnitt 8.3.10, „Optimiererverwendung generierter Spaltenindizes“ .

5.7. Aggregation von JSON-Werten

Bei der Aggregation von JSON-Werten NULLwerden SQL-Werte wie andere Datentypen ignoriert. Nichtwerte NULLwerden in numerische Typen konvertiert und aggregiert, mit Ausnahme von MIN(), MAX()und GROUP_CONCAT(). Bei numerischen skalaren JSON-Werten sollte die Konvertierung in eine Zahl aussagekräftige Ergebnisse liefern, obwohl es (abhängig vom Wert) zu Kürzungen und Genauigkeitsverlusten kommen kann. Das Konvertieren anderer JSON-Werte in Zahlen führt möglicherweise zu keinen aussagekräftigen Ergebnissen.

5.8. Verwandte Referenzen:

Abschnitt 8.3.10, „Optimiererverwendung generierter Spaltenindizes“

Abschnitt 9.1.2, „Numerische Literale“

Abschnitt 11.7, „Speicheranforderungen für Datentypen“

Abschnitt 12.3, „Typkonvertierungen in der Ausdrucksauswertung“

Abschnitt 12.17.11, „Spatial GeoJSON-Funktionen“

Abschnitt 12.18, „JSON-Funktionen“

Abschnitt 12.18.2, „Funktionen zum Erstellen von JSON-Werten“

Abschnitt 12.18.3, „Funktionen zum Suchen von JSON-Werten“

Abschnitt 13.1.18.8, Indizieren generierter Spalten zur Bereitstellung von JSON-Spaltenindizes

6. Standardwert des Datentyps

7. Speicheranforderungen für Datentypen

7.1. Speicheranforderungen für InnoDB-Tabellen

7.2、 NDB 表存储要求

7.3、 数字类型存储要求

7.4、 日期和时间类型存储要求

7.5、 字符串类型存储要求

7.6、 空间类型存储要求

7.7、 JSON 存储要求

7.8、相关参考

磁盘上表数据的存储要求取决于几个因素。不同的存储引擎表示数据类型和存储原始数据的方式不同。表数据可能会针对一列或整行进行压缩,从而使表或列的存储要求的计算变得复杂。

尽管磁盘上的存储布局存在差异,但用于通信和交换有关表行信息的内部 MySQL API 使用适用于所有存储引擎的一致数据结构。

本节包括 MySQL 支持的每种数据类型的存储要求的指南和信息,包括使用固定大小表示的数据类型的存储引擎的内部格式和大小。信息按类别或存储引擎列出。

表的内部表示最大行大小为 65,535 字节,即使存储引擎能够支持更大的行。此数字不包括 BLOBTEXT列,它们仅占此大小的 9 到 12 个字节。对于 BLOBTEXT数据,信息在内部存储在与行缓冲区不同的内存区域中。不同的存储引擎根据它们用于处理相应类型的方法,以不同的方式处理这些数据的分配和存储。有关详细信息,请参阅第 15 章,替代存储引擎第 8.4.7 节,“表列数和行大小的限制”

7.1、 InnoDB 表存储要求

有关 InnoDB 表的存储要求的信息, 请参阅第 14.11 节,“InnoDB 行格式”

7.2、 NDB 表存储要求

(跳过)

7.3、 数字类型存储要求

数据类型 需要存储
TINYINT 1 个字节
SMALLINT 2 个字节
MEDIUMINT 3 个字节
INT, INTEGER 4 个字节
BIGINT 8 个字节
FLOAT(p) 4 个字节( 0 <= p<= 24 ) ,8 个字节( 25 <= p<= 53 )
FLOAT 4 个字节
DOUBLE [PRECISION], REAL 8 个字节
DECIMAL(M,D), NUMERIC(M,D) 变长的; 见以下讨论
BIT(M) 大约 ( M+7)/8 字节

DECIMAL( 和 NUMERIC ) 列的值使用二进制格式表示,该格式将九个十进制(以 10 为基数)数字打包成四个字节。每个值的整数和小数部分的存储分别确定。每个九位数字的倍数需要四个字节,而“剩余” 数字需要四个字节的一部分。下表给出了多余数字所需的存储空间。

剩余数字 字节数
0 0
1, 2 1
3, 4 2
5, 6 3
7, 8 4

7.4、 日期和时间类型存储要求

对于TIMEDATETIMETIMESTAMP列,在 MySQL 5.6.4 之前创建的表所需的存储空间与从 5.6.4 开始创建的表不同。这是由于 5.6.4 中的更改允许这些类型具有小数部分,这需要 0 到 3 个字节。

数据类型 MySQL 5.6.4 之前需要存储 MySQL 5.6.4 所需的存储空间
YEAR 1 个字节 1 个字节
DATE 3 个字节 3 个字节
TIME 3 个字节 3 字节 + 小数秒存储
DATETIME 8 个字节 5 字节 + 小数秒存储
TIMESTAMP 4字节 4 字节 + 小数秒存储

从 MySQL 5.6.4 开始,存储 YEARDATE保持不变。但是, TIMEDATETIMETIMESTAMP的表示方式不同。DATETIME打包的效率更高,非小数部分需要 5 个而不是 8 个字节,并且所有3种表示时间的类型的小数部分只需要 0 到 3 个字节,具体取决于存储值的小数秒精度。

小数秒精度 需要存储
0 0 字节
1, 2 1 个字节
3, 4 2 个字节
5, 6 3 个字节

例如,TIME(0)TIME(2)TIME(4)TIME(6)分别使用 3(3+0)、4(3+1)、5(3+2) 和 6(3+3) 个字节。TIMETIME(0)是等效的并且需要相同的存储空间。

有关时间值的内部表示的详细信息,请参阅 MySQL 内部:重要的算法和结构

7.5、 字符串类型存储要求

在下表中,*M*表示非二进制字符串类型的声明列长度(字符长度)和二进制字符串类型的字节数。 *L*表示给定字符串值以字节为单位的实际长度(字节长度)。

数据类型 需要存储
CHAR(M) 紧凑的 InnoDB 行格式系列优化了可变长度字符集的存储。请参阅 COMPACT 行格式存储特性 。否则,M × w 字节 <= M <= 255,其中 w 是字符集中最大长度字符所需的字节数。
BINARY(M) *M*字节,0 <= M <= 255
VARCHAR(M), VARBINARY(M) L+1 个字节(如果列值需要 0 - 255 个字节),L+2 个字节(如果列值超过 255 个字节)
TINYBLOB, TINYTEXT L+ 1 个字节,其中 L< 2[^8] = 256 B
BLOB, TEXT L+ 2 个字节,其中 L< 2[^16] = 64 KB
MEDIUMBLOB, MEDIUMTEXT L+ 3 个字节,其中 L< 2[^24] = 16 MB
LONGBLOB, LONGTEXT L+ 4 个字节,其中 L< 2[^32] = 4 GB
ENUM('value1','value2',...) 1 或 2 个字节,取决于枚举值的数量(最多 65,535 个值)
SET('value1','value2',...) 1、2、3、4 或 8 个字节,取决于集合成员的数量(最多 64 个成员)

可变长度字符串类型使用长度前缀加数据存储。长度前缀根据数据类型需要一到四个字节,数据值需要 L(字符串的字节长度)。例如,一个 MEDIUMTEXT值的存储需要 *L*字节来存储值加上三个字节来存储值的长度。

要计算用于存储特定 CHARVARCHARTEXT列值的字节数,您必须考虑用于该列的字符集以及该值是否包含多字节字符。特别是,在使用 utf8 Unicode 字符集时,您必须牢记并非所有字符都使用相同的字节数。utf8mb3utf8mb4 字符集每个字符最多分别需要三个和四个字节。有关用于不同类别 utf8mb3utf8mb4 字符的存储细分,请参阅 第 10.9 节,“Unicode 支持”

VARCHAR, VARBINARY, BLOBTEXT类型是变长类型。对于它们的每个,存储要求取决于以下因素:

  • 列值的实际长度
  • 列的最大可能长度
  • 列使用的字符集,因为有些字符集包含多字节字符

例如,一个 VARCHAR(255) 列可以包含最大长度为 255 个字符的字符串。假设该列使用latin1字符集(每个字符一个字节),实际需要的存储是字符串的长度(L),加上一个字节来记录字符串的长度。对于字符串 'abcd',*L*是 4 并且存储要求是 5 个字节。如果同一列改为使用ucs2双字节字符集,则存储要求为 10 个字节: 'abcd' 的长度为 8 个字节,该列需要两个字节来存储长度,因为最大长度大于 255(最多 510字节)。

一个 VARCHARVARBINARY 列中可以存储的最大有效字节数取决于最大行大小 65,535 字节,该最大行大小在所有列之间共享。对于存储多字节字符的 VARCHAR 列,最大有效字符数较少。例如, utf8mb3 的每个字符最多需要三个字节,因此可以将使用 utf8mb3 字符集的 VARCHAR 列声明为最多 21,844 个字符。请参阅 第 8.4.7 节,“表列数和行大小的限制”

InnoDB将长度大于或等于 768 字节的固定长度字段编码为可变长度字段,可以在页外存储。例如, CHAR(255)如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像utf8mb4

NDB存储引擎支持可变宽度列 。这意味着 VARCHARNDB Cluster 表中的列需要与任何其他存储引擎相同的存储量,除了这些值是 4 字节对齐的。因此,使用字符集 latin1 存储在 VARCHAR(50)列中的 'abcd' 字符串需要 8 个字节(而不是 MyISAM表中相同列值的 5 个字节)。

(此处省略NDB相关的其他描述)NDB_COLUMN有关详细信息,请参阅 NDB_COLUMN 选项

ENUM 对象的大小由不同枚举值的数量决定。一个字节用于最多包含 255 个可能值的枚举。两个字节用于具有 256 到 65,535 个可能值的枚举。请参阅 第 11.3.5 节,“ENUM 类型”

SET 对象的大小由不同集合成员的数量决定。如果设置大小为*N*,则对象占用 (N+7)/8 字节,四舍五入为 1、2、3、4 或 8 个字节。一个 SET 最多可以有 64 个成员。请参阅 第 11.3.6 节,“SET 类型”

7.6、 空间类型存储要求

MySQL 使用 4 个字节存储空间值以指示 SRID,后跟该值的 WKB 表示。该 LENGTH()函数返回值存储所需的空间(以字节为单位)。

有关空间值的 WKB 和内部存储格式的描述,请参阅第 11.4.3 节,“支持的空间数据格式”

7.7、 JSON 存储要求

通常, JSON 列的存储要求与 LONGBLOBLONGTEXT 列的存储要求大致相同;也就是说,JSON 文档占用的空间与存储在其中一种类型的列中的文档字符串表示所占用的空间大致相同。但是,存储在 JSON 文档中的各个值的二进制编码(包括查找所需的元数据和字典)会产生开销。例如,存储在 JSON 文档中的字符串需要 4 到 10 个字节的额外存储空间,具体取决于字符串的长度以及存储它的对象或数组的大小。

此外,MySQL 对存储在JSON列中的任何 JSON 文档的大小施加了限制,使其不能大于 max_allowed_packet.

7.8、相关参考

第 8.4.7 节,“表列数和行大小的限制”

第 10.9 节,“Unicode 支持”

第 11.3.5 节,“ENUM 类型”

第 11.3.6 节,“SET 类型”

第 14.11 节,“InnoDB 行格式”

第 14.11 节,COMPACT 行格式存储特性

第 15 章,替代存储引擎

MySQL 内部:重要的算法和结构

8、为列选择正确的类型

9、使用来自其他数据库引擎的数据类型

Ich denke du magst

Origin blog.csdn.net/booynal/article/details/125705927
Empfohlen
Rangfolge