programmera.net -> mysql -> normal     för utskrift      info@programmera.net

Texttyper i MySQL

1. Texttyper
2. Texttyper och DEFAULT
3. Texttyper och NULL
4. Texttyper och felaktiga invärden
5. Binära och ickebinära strängar
6. CHAR och VARCHAR
7. Implicita konverteringar mellan CHAR och VARCHAR
8. TEXT och BLOB

1. Texttyper

De datatyper som MySQL använder för att lagra text är:

Datatyp Längd i bytes Maxlängd Beskrivning
CHAR  MAX  MAX < 256  Innehåller text eller bytes. Fix längd med maxlängd som bestämms då kolumnen skapas. Maxlängden måste dock bestämmas till ett tal < 256.
VARCHAR  L+1  MAX < 256  Innehåller text eller bytes. Variabel längd (L) med en maxlängd som bestämms då kolumnen skapas. Maxlängden måste dock bestämmas till ett tal < 256. 1 byte används för att lagra längden på texten.
TINYTEXT  L+1  255  Innehåller text. Variabel längd (L) med en maxlängd 255. 1 byte används för att lagra längden på texten.
TEXT  L+2  65,535  Innehåller text. Variabel längd (L) med en maxlängd 2^16. 2 byte används för att lagra längden på texten.
MEDIUMTEXT  L+3  16,777,215  Innehåller text. Variabel längd (L) med en maxlängd 2^24. 3 byte används för att lagra längden på texten.
LONGTEXT  L+4  4,294,967,295  Innehåller text. Variabel längd (L) med en maxlängd 2^32. 4 byte används för att lagra längden på texten.
TINYBLOB  L+1  255  Innehåller bytes. Variabel längd (L) med en maxlängd 255. 1 byte används för att bestämma hur många bytes som lagras.
BLOB  L+2  65,535  Innehåller bytes. Variabel längd (L) med en maxlängd 2^16. 2 byte används för att bestämma hur många bytes som lagras.
MEDIUMBLOB  L+3  16,777,215  Innehåller bytes. Variabel längd (L) med en maxlängd 2^24. 3 byte används för att bestämma hur många bytes som lagras.
LONGBLOB  L+4  4,294,967,295  Innehåller bytes. Variabel längd (L) med en maxlängd 2^32. 4 byte används för att bestämma hur många bytes som lagras.

2. Texttyper och DEFAULT

Om man inte skriver ett explicit värde för en kolumn i en INSERT-sats lagras ett defaultvärde.

  1. En kolumn som har ett explicit defaultvärde lagrar defaultvärdet.
  2. En kolumn som ej har ett explicit defaultvärde och som kan innehålla NULL, lagrar NULL.
  3. En kolumn som ej har ett explicit defaultvärde och som ej kan innehålla NULL, lagrar tomma strängen ("").
Vi testar defaultvärden för 3 olika fall:
mysql> CREATE TABLE text_table (
    -> text_col1 VARCHAR(100) DEFAULT 'foo',
    -> text_col2 VARCHAR(100),
    -> text_col3 VARCHAR(100) NOT NULL
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO text_table VALUES ();
Query OK, 1 row affected (0.02 sec)

mysql> SELECT * FROM text_table\G
*************************** 1. row ***************************
text_col1: foo
text_col2: NULL
text_col3:
1 row in set (0.00 sec)

3. Texttyper och NULL

Om man explicit försöker lagra NULL i en textkolumn har vi följande fall:

  1. Om en kolumn kan innehålla NULL sätts den till NULL.
  2. Om en NOT NULL-kolumn sätts till NULL i en UPDATE får kolumnen värdet tomma strängen, och en varning läggs till på slutet.
  3. Om en NOT NULL-kolumn sätts till NULL i en INSERT genereras ett fel och satsen abryts.
Följande exempel illustrerar fall 2 ovan:
mysql> UPDATE text_table SET text_col3="hej";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
	
mysql> SELECT text_col3 FROM text_table;
+-----------+
| text_col3 |
+-----------+
| hej       |
+-----------+
1 row in set (0.00 sec)

mysql> UPDATE text_table SET text_col3=NULL;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

mysql> SELECT text_col3 FROM text_table;
+-----------+
| text_col3 |
+-----------+
|           |
+-----------+
1 row in set (0.00 sec)
Alltså, när du sätter text_col3 (som är deklarerad med NOT NULL) till NULL med UPDATE får du inget fel, bara en varning. Däremot då du försöker sätta kolumnen till NULL i en INSERT händer följande:
mysql> INSERT INTO text_table VALUES(NULL,NULL,NULL);
ERROR 1048: Column 'text_col3' cannot be null

4. Texttyper och felaktiga invärden

Eftersom texttyper kan lagra i princip vad som helst är det enda felet man kan göra då man lagrar data att man lagrar för många tecken. Lagrar man för många tecken trunkeras texten så att bara de första lagras. Nedan visar jag ett exempel på det:
mysql> CREATE TABLE text_table (
    -> text_col VARCHAR(5)
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO text_table VALUES ("abcdefgh");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM text_table;
+----------+
| text_col |
+----------+
| abcde    |
+----------+
1 row in set (0.00 sec)

5. Binära och ickebinära strängar

En binär sträng behandlas som en serie rena bytes. Detta innebär att vid jämförelse mellan två strängar jämförs strängarna byte för byte. Märk speciellt följande:

  • En stor bokstav har ett annat byte-värde än en liten.
  • En bokstav med accent har ett annat byte-värde än en bokstav utan accent.
En ickebinär sträng behandlas som en serie tecken, tillhörande en teckenuppsättning. Strängen tolkas alltså på en högre nivå än bytenivå. I MySQL är teckengruppen per default Latin-1 ( även kallad ISO-8859-1). Latin-1 kräver bara en byte per tecken, men andra teckenuppsättningar kräver ibland mer. Varje teckenuppensättning har en sorteringsordning som bestämmer på vilket sätt olika tecken ska ordnas. Detta innebär att vid jämförelse mellan två strängar jämförs tecken för tecken efter denna sorteringsordning. Detta får följande konsekvenser:
  • Teckenjämförelsen behöver inte bry sig om stora och små bokstäver. Latin-1 ser "AbC" som ekvivalent med "abc".
  • Teckenjämförelsen behöver inte bry sig om accenter. Latin-1 ser "á" som ekvivalent med "a".
Ett exempel:
mysql> CREATE TABLE text_table(
    -> text_col varchar(100)
    -> );
Query OK, 0 rows affected (0.09 sec)

INSERT INTO text_table VALUES ("a"),("A"),("á"),("à");
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

SELECT * FROM text_table WHERE text_col="a";
+----------+
| text_col |
+----------+
| a        |
| A        |
| á        |
| à        |
+----------+
4 rows in set (0.00 sec)
Som synes i exemplet ovan ser MySQL alla tecknen som ekvivalenta.

6. CHAR och VARCHAR

Typerna CHAR och VARCHAR kan lagra både text och bytes. För att lagra bytes deklarerar man kolumnen med nyckelordet BINARY. Den enda skillnaden mellan CHAR och VARCHAR är hur MySQL lagrar själva datat:

  • CHAR har fix maxlängd (MAX < 256) som du bestämmer vid skapandet av kolumnen. Försöker du lagra en sträng som är längre än MAX kommer strängen att trunkeras. Om du försöker att lagra en sträng som är kortare än MAX fylls strängen ut med mellanslag så att längden blir MAX.
  • VARCHAR har också en fix maxlängd (MAX < 256) som du bestämmer vid skapandet av kolumnen. Om du försöker lagra en text längre än MAX kommer strängen att trunkeras. Om du däremot lagrar en text som är kortare än MAX kommer bara den text du skickar in att lagras. En extra byte används för att bestämma längden på den aktuella strängen.
MySQL trunkerar alltid utskriften på CHAR vid utskift så att de mellanslag som fyller fältet upp till MAX försvinner. Se exemplet nedan:
mysql> CREATE TABLE text_tab(
    -> c_col_1 CHAR(4),
    -> c_col_2 CHAR(30)
    -> );
Query OK, 0 rows affected (0.06 sec)

DESC text_tab;
+---------+----------+------+-----+---------+-------+
| Field   | Type     | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| c_col_1 | char(4)  | YES  |     | NULL    |       |
| c_col_2 | char(30) | YES  |     | NULL    |       |
+---------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

INSERT INTO text_tab VALUES("abcdefg", "abcdef");
Query OK, 1 row affected (0.00 sec)

SELECT * FROM text_tab;
+---------+---------+
| c_col_1 | c_col_2 |
+---------+---------+
| abcd    | abcdef  |
+---------+---------+
1 row in set (0.00 sec)

SELECT CHAR_LENGTH(c_col_1), CHAR_LENGTH(c_col_2) FROM text_tab;
+----------------------+----------------------+
| CHAR_LENGTH(c_col_1) | CHAR_LENGTH(c_col_2) |
+----------------------+----------------------+
|                    4 |                    6 |
+----------------------+----------------------+
1 row in set (0.02 sec)
Utifrån exemplet ovan beter sig CHAR precis som VARCHAR. Hur vet vi att MySQL inte i hemlighet lagrar all text med variabel längd? För att kolla detta måste vi gå in och titta i själva datafilen. Exemplet nedan visar att CHAR faktiskt lagrar ett tecken för varje tecken i sin längd:
mysql> CREATE TABLE long_char_tab(
    -> c_col CHAR(250)
    -> );
Query OK, 0 rows affected (0.03 sec)

INSERT INTO long_char_tab VALUES ("1"),("2"),("3"),("4"),("5"),("6"),("7"),("8"),("9"),("10"),("11");
Query OK, 11 rows affected (0.00 sec)
Records: 11  Duplicates: 0  Warnings: 0

CREATE TABLE long_varchar_tab(
    -> vc_col VARCHAR(250)
    -> );
Query OK, 0 rows affected (0.05 sec)

INSERT INTO long_varchar_tab VALUES ("1"),("2"),("3"),("4"),("5"),("6"),("7"),("8"),("9"),("10"),("11");
Query OK, 11 rows affected (0.00 sec)
Records: 11  Duplicates: 0  Warnings: 0
Vi öppnar filen MYSQL_HOME/data/test/long_char_tab.MYD som innehåller tabellens data:



Vi ser att filens storlek är ((250+1)*11=) 2761 byte stor. När vi öppnar filen MYSQL_HOME/data/test/long_varchar_tab.MYD ser vi att den är betydligt mindre:



Storleken är 220 bytes.

7. Implicita konverteringar mellan CHAR och VARCHAR

Ibland förekommer en automatiskt konvertering mellan CHAR och VARCHAR av MySQL. Konverteringen följer följande regler:

  • VARCHAR blir CHAR om längden är 3 eller kortare. På detta sätt slipper MySQL lagra den byte som bestämmer längden på textsträngen.
  • CHAR blir VARCHAR om längden på CHAR är längre än 3 och det finns en annan kolumn med variabel längd i tabellen. Eftersom varje rad i tabellen ändå kommer att ha variabel längd (och därför inte går så snabbt att söka i) konverteras alla CHAR till VARCHAR för att spara plats.
Följande exempel illustrerar hur MySQL ibland konverterar mellan typerna CHAR och VARCHAR:
mysql>  CREATE TABLE conv_tab(
    -> vc_col_1 VARCHAR(3),
    -> c_col_1 CHAR(4),
    -> vc_col_2 VARCHAR(7)
    -> );
Query OK, 0 rows affected (0.03 sec)

 DESC conv_tab;
+----------+------------+------+-----+---------+-------+
| Field    | Type       | Null | Key | Default | Extra |
+----------+------------+------+-----+---------+-------+
| vc_col_1 | char(3)    | YES  |     | NULL    |       |
| c_col_1  | varchar(4) | YES  |     | NULL    |       |
| vc_col_2 | varchar(7) | YES  |     | NULL    |       |
+----------+------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
Vi ser att "vc_col_1" lagrar CHAR istället för VARCHAR eftersom den är kortare än 4 tecken. Kolumnen "c_col_1" har bytt typ till VARCHAR, detta eftersom tabellen har en annan kolumn av variabel längd (vc_col_2).

8. TEXT och BLOB

Typerna TEXT och BLOB är i princip identiska men de skiljer sig åt på följande punkt:

  • TEXT lagrar text som tecken.
  • BLOB (Binary Large OBject) lagrar bytes. BLOB bör användas för lagring av bilder och annan binär data, men kan även lagra text.
Dessa två typer kommer i 4 storlekar:
  • TINY(TEXT/BLOB) lagrar som mest 255 bytes/tecken. Storleken på strängen lagras i en byte.
  • (TEXT/BLOB) lagrar som mest 65,535 bytes/tecken. Storleken på strängen lagras i två bytes.
  • MEDIUM(TEXT/BLOB) lagrar som mest 16,777,215 bytes/tecken. Storleken på strängen lagras i tre bytes.
  • LONG(TEXT/BLOB) lagrar som mest 4,294,967,295 bytes/tecken. Storleken på strängen lagras i fyra bytes.