文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  LOAD DATA 语句

15.2.9 LOAD DATA 语句

LOAD DATA
    [LOW_PRIORITY | CONCURRENT] [LOCAL]
    INFILE 'file_name'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [PARTITION (partition_name [, partition_name] ...)]
    [CHARACTER SET charset_name]
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number {LINES | ROWS}]
    [(col_name_or_user_var
        [, col_name_or_user_var] ...)]
    [SET col_name={expr | DEFAULT}
        [, col_name={expr | DEFAULT}] ...]

LOAD DATA 语句以非常高的速度将文本文件中的行读取到表中。根据是否指定了 LOCAL 修饰符,可以从服务器主机或客户端主机读取文件。LOCAL 也会影响数据的解释和错误处理。

LOAD DATASELECT ... INTO OUTFILE 的补充。(请参阅 第 15.2.13.1 节,“SELECT ... INTO 语句”。)要将表中的数据写入文件,请使用 SELECT ... INTO OUTFILE。要将文件读回表中,请使用 LOAD DATAFIELDSLINES 子句的语法对于这两种语句是相同的。

mysqlimport 实用程序提供了另一种加载数据文件的方法;它通过向服务器发送 LOAD DATA 语句来实现。请参阅 第 6.5.5 节,“mysqlimport — 数据导入程序”

有关 INSERTLOAD DATA 的效率以及如何加快 LOAD DATA 速度的信息,请参阅第 10.2.5.1 节 “优化 INSERT 语句”

非 LOCAL 与 LOCAL 操作

与非 LOCAL 操作相比,LOCAL 修饰符会影响 LOAD DATA 的以下方面:

仅当服务器和客户端都配置为允许时,LOCAL 才会起作用。例如,如果使用禁用了 local_infile 系统变量的 mysqld 启动,则 LOCAL 会产生错误。请参阅第 8.1.6 节 “LOAD DATA LOCAL 的安全注意事项”

输入文件字符集

文件名必须指定为文字字符串。在 Windows 上,使用正斜杠或双反斜杠指定路径名中的反斜杠。服务器使用 character_set_filesystem 系统变量指示的字符集解释文件名。

默认情况下,服务器使用 character_set_database 系统变量指示的字符集解释文件内容。如果文件内容使用的字符集与此默认字符集不同,最好使用 CHARACTER SET 子句指定该字符集。binary 字符集指定不转换。

SET NAMEScharacter_set_client 的设置不会影响文件内容的解释。

LOAD DATA 将文件中的所有字段解释为具有相同的字符集,而不管将字段值加载到的列的数据类型如何。为了正确解释文件,必须确保使用正确的字符集编写文件。例如,如果使用 mysqldump -T 或通过在 mysql 中发出 SELECT ... INTO OUTFILE 语句来编写数据文件,请确保使用 --default-character-set 选项以在使用 LOAD DATA 加载文件时要使用的字符集中写入输出。

注意

无法加载使用 ucs2utf16utf16leutf32 字符集的数据文件。

输入文件位置

以下规则确定 LOAD DATA 输入文件的位置:

  • 如果未指定 LOCAL,则文件必须位于服务器主机上。服务器直接读取文件,并按如下方式定位文件:

    • 如果文件名是绝对路径名,则服务器按原样使用它。

    • 如果文件名是带有前导组件的相对路径名,则服务器在其数据目录中查找该文件。

    • 如果文件名没有前导组件,则服务器在默认数据库的数据库目录中查找该文件。

  • 如果指定了 LOCAL,则文件必须位于客户端主机上。客户端程序读取文件,并按如下方式定位文件:

    • 如果文件名是绝对路径名,则客户端程序按原样使用它。

    • 如果文件名是相对路径名,则客户端程序在其调用目录中查找该文件。

    使用 LOCAL 时,客户端程序读取文件并将其内容发送到服务器。服务器在其存储临时文件的目录中创建文件的副本。请参阅第 B.3.3.5 节 “MySQL 存储临时文件的位置”。如果此目录中没有足够的空间容纳副本,则会导致 LOAD DATA LOCAL 语句失败。

LOCAL 规则意味着服务器读取名为 ./myfile.txt 的文件(相对于其数据目录),而它从默认数据库的数据库目录中读取名为 myfile.txt 的文件。例如,如果在 db1 是默认数据库的情况下执行以下 LOAD DATA 语句,则服务器会从 db1 的数据库目录中读取文件 data.txt,即使该语句明确将文件加载到 db2 数据库中的表中也是如此:

LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
注意

服务器还使用非 LOCAL 规则为 IMPORT TABLE 语句定位 .sdi 文件。

安全要求

对于非 LOCAL 加载操作,服务器会读取服务器主机上的文本文件,因此必须满足以下安全要求:

  • 您必须具有 FILE 权限。请参阅第 8.2.2 节 “MySQL 提供的权限”

  • 该操作受 secure_file_priv 系统变量设置的约束:

    • 如果变量值是非空的目录名,则文件必须位于该目录中。

    • 如果变量值为空(这是不安全的),则文件只需对服务器可读即可。

对于 LOCAL 加载操作,客户端程序会读取客户端主机上的文本文件。因为文件内容是由客户端通过连接发送到服务器的,所以使用 LOCAL 比服务器直接访问文件时要慢一些。另一方面,您不需要 FILE 权限,并且文件可以位于客户端程序可以访问的任何目录中。

重复键和错误处理

REPLACEIGNORE 修饰符控制如何处理在唯一键值(PRIMARY KEYUNIQUE 索引值)上与现有表行重复的新(输入)行:

LOCAL 修饰符与 IGNORE 具有相同的效果。这是因为服务器无法在操作过程中停止文件的传输。

如果未指定 REPLACEIGNORELOCAL,则在找到重复的键值时会发生错误,并且会忽略文本文件的其余部分。

除了像刚才描述的那样影响重复键处理之外,IGNORELOCAL 还会影响错误处理:

  • 如果既不使用 IGNORE 也不使用 LOCAL,则数据解释错误会终止操作。

  • 使用 IGNORELOCAL 时,数据解释错误会变为警告,并且加载操作会继续,即使 SQL 模式是限制性的也是如此。有关示例,请参阅列值赋值

索引处理

要在加载操作期间忽略外键约束,请在执行 LOAD DATA 之前执行 SET foreign_key_checks = 0 语句。

如果在空的 MyISAM 表上使用 LOAD DATA,则所有非唯一索引都会在一个单独的批处理中创建(与 REPAIR TABLE 一样)。通常,当您有许多索引时,这会使 LOAD DATA 快得多。在某些极端情况下,您可以通过在将文件加载到表中之前使用 ALTER TABLE ... DISABLE KEYS 关闭索引,并在加载文件之后使用 ALTER TABLE ... ENABLE KEYS 重新创建索引,来更快地创建索引。请参阅第 10.2.5.1 节 “优化 INSERT 语句”

字段和行处理

对于 LOAD DATASELECT ... INTO OUTFILE 语句,FIELDSLINES 子句的语法相同。这两个子句都是可选的,但如果同时指定了这两个子句,则 FIELDS 必须位于 LINES 之前。

如果指定了 FIELDS 子句,则其每个子子句(TERMINATED BY[OPTIONALLY] ENCLOSED BYESCAPED BY)也是可选的,但必须至少指定其中一个。这些子句的参数只允许包含 ASCII 字符。

如果未指定 FIELDSLINES 子句,则默认值与编写以下内容时的默认值相同:

FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
LINES TERMINATED BY '\n' STARTING BY ''

反斜杠是 SQL 语句中字符串内的 MySQL 转义字符。因此,要指定文字反斜杠,必须指定两个反斜杠,以便将该值解释为单个反斜杠。转义序列 '\t''\n' 分别指定制表符和换行符。

换句话说,默认情况下,LOAD DATA 在读取输入时会执行以下操作

  • 在新行处查找行边界。

  • 不跳过任何行前缀。

  • 在制表符处将行分割成字段。

  • 不要求字段包含在任何引号字符中。

  • 将前面带有转义字符 \ 的字符解释为转义序列。例如,\t\n\\ 分别表示制表符、换行符和反斜杠。有关转义序列的完整列表,请参阅稍后对 FIELDS ESCAPED BY 的讨论。

相反,默认情况下,SELECT ... INTO OUTFILE 在写入输出时会执行以下操作

  • 在字段之间写入制表符。

  • 不要将字段包含在任何引号字符中。

  • 使用 \ 转义字段值中出现的制表符、换行符或 \

  • 在行尾写入换行符。

注意

对于在 Windows 系统上生成的文本文件,正确读取文件可能需要 LINES TERMINATED BY '\r\n',因为 Windows 程序通常使用两个字符作为行终止符。某些程序(如 WordPad)在写入文件时可能会使用 \r 作为行终止符。要读取此类文件,请使用 LINES TERMINATED BY '\r'

如果所有输入行都有一个要忽略的公共前缀,则可以使用 LINES STARTING BY 'prefix_string' 跳过前缀及其前面的任何内容。如果一行不包含前缀,则会跳过整行。假设您发出以下语句

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test
  FIELDS TERMINATED BY ','  LINES STARTING BY 'xxx';

如果数据文件如下所示

xxx"abc",1
something xxx"def",2
"ghi",3

结果行为 ("abc",1)("def",2)。文件中的第三行将被跳过,因为它不包含前缀。

IGNORE number LINES 子句可用于忽略文件开头的行。例如,您可以使用 IGNORE 1 LINES 跳过包含列名的初始标题行

LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test IGNORE 1 LINES;

当您将 SELECT ... INTO OUTFILELOAD DATA 结合使用以将数据从数据库写入文件,然后稍后将文件读回数据库时,两个语句的字段和行处理选项必须匹配。否则,LOAD DATA 将无法正确解释文件内容。假设您使用 SELECT ... INTO OUTFILE 写入一个文件,其中字段以逗号分隔

SELECT * INTO OUTFILE 'data.txt'
  FIELDS TERMINATED BY ','
  FROM table2;

要读取以逗号分隔的文件,正确的语句是

LOAD DATA INFILE 'data.txt' INTO TABLE table2
  FIELDS TERMINATED BY ',';

相反,如果您尝试使用以下语句读取文件,则该语句将不起作用,因为它指示 LOAD DATA 在字段之间查找制表符

LOAD DATA INFILE 'data.txt' INTO TABLE table2
  FIELDS TERMINATED BY '\t';

结果很可能是将每行输入解释为单个字段。

LOAD DATA 可用于读取从外部源获取的文件。例如,许多程序可以以逗号分隔值 (CSV) 格式导出数据,以便行中的字段以逗号分隔并包含在双引号中,第一行是列名。如果此类文件中的行由回车/换行符对终止,则此处显示的语句说明了用于加载文件的字段和行处理选项

LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\r\n'
  IGNORE 1 LINES;

如果输入值不一定包含在引号中,请在 ENCLOSED BY 选项之前使用 OPTIONALLY

任何字段或行处理选项都可以指定空字符串 ('')。如果非空,则 FIELDS [OPTIONALLY] ENCLOSED BYFIELDS ESCAPED BY 值必须是单个字符。FIELDS TERMINATED BYLINES STARTING BYLINES TERMINATED BY 值可以是多个字符。例如,要写入以回车/换行符对终止的行,或者要读取包含此类行的文件,请指定 LINES TERMINATED BY '\r\n' 子句。

要读取包含由 %% 组成的行分隔的笑话的文件,您可以执行以下操作

CREATE TABLE jokes
  (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  joke TEXT NOT NULL);
LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes
  FIELDS TERMINATED BY ''
  LINES TERMINATED BY '\n%%\n' (joke);

FIELDS [OPTIONALLY] ENCLOSED BY 控制字段的引用。对于输出(SELECT ... INTO OUTFILE),如果省略单词 OPTIONALLY,则所有字段都将包含在 ENCLOSED BY 字符中。此类输出的示例(使用逗号作为字段分隔符)如下所示

"1","a string","100.20"
"2","a string containing a , comma","102.20"
"3","a string containing a \" quote","102.20"
"4","a string containing a \", quote and comma","102.20"

如果指定 OPTIONALLY,则 ENCLOSED BY 字符仅用于包含来自具有字符串数据类型(如 CHARBINARYTEXTENUM)的列的值

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a \" quote",102.20
4,"a string containing a \", quote and comma",102.20

字段值中出现的 ENCLOSED BY 字符可以通过在其前面加上 ESCAPED BY 字符来转义。此外,如果指定空的 ESCAPED BY 值,则可能会无意中生成 LOAD DATA 无法正确读取的输出。例如,如果转义字符为空,则前面显示的输出将如下所示。请注意,第四行中的第二个字段在引号后面包含一个逗号,该逗号(错误地)似乎终止了该字段

1,"a string",100.20
2,"a string containing a , comma",102.20
3,"a string containing a " quote",102.20
4,"a string containing a ", quote and comma",102.20

对于输入,ENCLOSED BY 字符(如果存在)将从字段值的末尾删除。(无论是否指定了 OPTIONALLY,都是如此;OPTIONALLY 对输入解释没有影响。)前面带有 ESCAPED BY 字符的 ENCLOSED BY 字符的出现将被解释为当前字段值的一部分。

如果字段以 ENCLOSED BY 字符开头,则仅当该字符后跟字段或行 TERMINATED BY 序列时,才会将其识别为终止字段值。为避免歧义,字段值中出现的 ENCLOSED BY 字符可以加倍,并解释为该字符的单个实例。例如,如果指定了 ENCLOSED BY '"',则引号的处理方式如下所示

"The ""BIG"" boss"  -> The "BIG" boss
The "BIG" boss      -> The "BIG" boss
The ""BIG"" boss    -> The ""BIG"" boss

FIELDS ESCAPED BY 控制如何读取或写入特殊字符

  • 对于输入,如果 FIELDS ESCAPED BY 字符不为空,则会删除该字符的出现,并将后面的字符按字面意思作为字段值的一部分。某些双字符序列是例外,其中第一个字符是转义字符。下表显示了这些序列(使用 \ 作为转义字符)。NULL 处理规则将在本节后面介绍。

    字符 转义序列
    \0 ASCII NUL (X'00') 字符
    \b 退格符
    \n 换行符
    \r 回车符
    \t 制表符。
    \Z ASCII 26 (Control+Z)
    \N NULL

    有关 \ 转义语法的更多信息,请参阅 第 11.1.1 节“字符串字面量”

    如果 FIELDS ESCAPED BY 字符为空,则不会进行转义序列解释。

  • 对于输出,如果 FIELDS ESCAPED BY 字符不为空,则它用于在输出中为以下字符添加前缀

    • FIELDS ESCAPED BY 字符。

    • FIELDS [OPTIONALLY] ENCLOSED BY 字符。

    • 如果 ENCLOSED BY 字符为空或未指定,则为 FIELDS TERMINATED BYLINES TERMINATED BY 值的第一个字符。

    • ASCII 0(转义字符后面实际写入的是 ASCII 0,而不是零值字节)。

    如果 FIELDS ESCAPED BY 字符为空,则不会转义任何字符,并且 NULL 将输出为 NULL,而不是 \N。指定空的转义字符可能不是一个好主意,特别是当数据中的字段值包含前面列表中的任何字符时。

在某些情况下,字段和行处理选项会相互影响

  • 如果 LINES TERMINATED BY 是空字符串,并且 FIELDS TERMINATED BY 不为空,则行也会以 FIELDS TERMINATED BY 终止。

  • 如果 FIELDS TERMINATED BYFIELDS ENCLOSED BY 值都为空 (''),则使用固定行(非分隔)格式。使用固定行格式时,字段之间不使用分隔符(但您仍然可以有行终止符)。相反,列值的读取和写入使用足以容纳字段中所有值的字段宽度。对于 TINYINTSMALLINTMEDIUMINTINTBIGINT,字段宽度分别为 4、6、8、11 和 20,无论声明的显示宽度是多少。

    LINES TERMINATED BY 仍然用于分隔行。如果一行不包含所有字段,则其余列将设置为其默认值。如果您没有行终止符,则应将其设置为 ''。在这种情况下,文本文件必须包含每行的所有字段。

    固定行格式也会影响 NULL 值的处理,如下所述。

    注意

    如果您使用的是多字节字符集,则固定大小格式将不起作用。

NULL 值的处理方式因使用的 FIELDSLINES 选项而异

  • 对于默认的 FIELDSLINES 值,对于输出,NULL 将写为字段值 \N,而对于输入,字段值 \N 将读取为 NULL(假设 ESCAPED BY 字符为 \)。

  • 如果 FIELDS ENCLOSED BY 不为空,则包含字面量 NULL 作为其值的字段将被读取为 NULL 值。这与包含在 FIELDS ENCLOSED BY 字符内的单词 NULL 不同,后者将被读取为字符串 'NULL'

  • 如果 FIELDS ESCAPED BY 为空,则 NULL 将被写为单词 NULL

  • 对于固定行格式(当 FIELDS TERMINATED BYFIELDS ENCLOSED BY 均为空时使用),NULL 将被写为空字符串。这会导致在写入文件时,表中的 NULL 值和空字符串无法区分,因为它们都被写为空字符串。如果需要在读回文件时区分这两者,则不应使用固定行格式。

尝试将 NULL 加载到 NOT NULL 列中会根据列值赋值中描述的规则产生警告或错误。

LOAD DATA 不支持某些情况

  • 固定大小的行(FIELDS TERMINATED BYFIELDS ENCLOSED BY 均为空)以及 BLOBTEXT 列。

  • 如果指定了一个分隔符与另一个分隔符相同或为其前缀,则 LOAD DATA 无法正确解释输入。例如,以下 FIELDS 子句会导致问题

    FIELDS TERMINATED BY '"' ENCLOSED BY '"'
  • 如果 FIELDS ESCAPED BY 为空,则包含 FIELDS ENCLOSED BYLINES TERMINATED BY 后跟 FIELDS TERMINATED BY 值的字段值会导致 LOAD DATA 过早停止读取字段或行。这是因为 LOAD DATA 无法正确确定字段或行值的结束位置。

列列表规范

以下示例加载 persondata 表的所有列

LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

默认情况下,如果在 LOAD DATA 语句的末尾没有提供列列表,则预期输入行包含表中每个列的字段。如果只想加载表中的某些列,请指定一个列列表

LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata
(col_name_or_user_var [, col_name_or_user_var] ...);

如果输入文件中字段的顺序与表中列的顺序不同,则还必须指定一个列列表。否则,MySQL 将无法知道如何将输入字段与表列匹配。

输入预处理

LOAD DATA 语法中的每个 col_name_or_user_var 实例都是列名或用户变量。使用用户变量,SET 子句允许您在将结果分配给列之前对其值执行预处理转换。

SET 子句中的用户变量可以多种方式使用。以下示例直接使用第一个输入列作为 t1.column1 的值,并将第二个输入列分配给一个用户变量,该变量在用于 t1.column2 的值之前进行除法运算

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @var1)
  SET column2 = @var1/100;

SET 子句可用于提供不是从输入文件派生的值。以下语句将 column3 设置为当前日期和时间

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, column2)
  SET column3 = CURRENT_TIMESTAMP;

您还可以通过将输入值分配给用户变量而不将该变量分配给任何表列来丢弃该输入值

LOAD DATA INFILE 'file.txt'
  INTO TABLE t1
  (column1, @dummy, column2, @dummy, column3);

列/变量列表和 SET 子句的使用受以下限制

  • SET 子句中的赋值语句在赋值运算符的左侧只能有列名。

  • 您可以在 SET 赋值语句的右侧使用子查询。返回要分配给列的值的子查询只能是标量子查询。此外,您不能使用子查询从正在加载的表中进行选择。

  • IGNORE number LINES 子句忽略的行不会针对列/变量列表或 SET 子句进行处理。

  • 使用固定行格式加载数据时不能使用用户变量,因为用户变量没有显示宽度。

列值赋值

为了处理输入行,LOAD DATA 会将其拆分为字段,并根据列/变量列表和 SET 子句(如果存在)使用这些值。然后将结果行插入到表中。如果表中存在 BEFORE INSERTAFTER INSERT 触发器,则它们将分别在插入行之前或之后被激活。

字段值的解释和对表列的分配取决于以下因素

  • SQL 模式(sql_mode 系统变量的值)。该模式可以是非限制性的,也可以是各种方式的限制性。例如,可以启用严格的 SQL 模式,或者该模式可以包含诸如 NO_ZERO_DATENO_ZERO_IN_DATE 之类的值。

  • IGNORELOCAL 修饰符的存在与否。

这些因素结合起来,通过 LOAD DATA 生成限制性或非限制性数据解释

  • 如果 SQL 模式是限制性的,并且未指定 IGNORELOCAL 修饰符,则数据解释是限制性的。错误将终止加载操作。

  • 如果 SQL 模式是非限制性的,或者指定了 IGNORELOCAL 修饰符,则数据解释是非限制性的。(特别是,如果指定了任一修饰符,则在省略 REPLACE 修饰符时,该修饰符将覆盖限制性 SQL 模式。)错误将变为警告,并且加载操作将继续。

限制性数据解释使用以下规则

  • 字段过多或过少会导致错误。

  • NULL(即 \N)分配给非 NULL 列会导致错误。

  • 超出列数据类型范围的值会导致错误。

  • 无效值会产生错误。例如,对于数字列,诸如 'x' 之类的值会导致错误,而不是转换为 0。

相反,非限制性数据解释使用以下规则

  • 如果输入行的字段过多,则将忽略多余的字段,并增加警告的数量。

  • 如果输入行的字段过少,则缺少输入字段的列将被分配其默认值。默认值分配在第 13.6 节“数据类型默认值”中进行了描述。

  • NULL(即 \N)分配给非 NULL 列会导致分配列数据类型的隐式默认值。隐式默认值在第 13.6 节“数据类型默认值”中进行了描述。

  • 无效值会产生警告而不是错误,并转换为列数据类型的最接近有效值。例子

    • 对于数字列,诸如 'x' 之类的值会导致转换为 0。

    • 超出范围的数字或时间值将被裁剪为列数据类型范围的最接近端点。

    • DATETIMEDATETIME 列的无效值将被插入为隐式默认值,而无论 SQL 模式 NO_ZERO_DATE 设置如何。隐式默认值是该类型的相应值('0000-00-00 00:00:00''0000-00-00''00:00:00')。请参阅第 13.2 节“日期和时间数据类型”

  • LOAD DATA 对空字段值的解释与对缺少字段的解释不同

    • 对于字符串类型,该列将设置为字符串。

    • 对于数字类型,该列将设置为 0

    • 对于日期和时间类型,该列将设置为该类型的相应值。请参阅第 13.2 节“日期和时间数据类型”

    这些值与在 INSERTUPDATE 语句中将空字符串显式分配给字符串、数字或日期或时间类型时产生的值相同。

仅当 TIMESTAMP 列的默认值为当前时间戳,并且在指定字段列表时从字段列表中省略该列时,TIMESTAMP 列才会设置为当前日期和时间。

LOAD DATA 将所有输入视为字符串,因此您不能像使用 INSERT 语句那样对 ENUMSET 列使用数值。所有 ENUMSET 值都必须指定为字符串。

不能使用二进制表示法(例如,b'011010')直接加载 BIT 值。要解决此问题,请使用 SET 子句去掉前导 b' 和尾随 ',并执行从基数 2 到基数 10 的转换,以便 MySQL 将值正确加载到 BIT 列中

$> cat /tmp/bit_test.txt
b'10'
b'1111111'
$> mysql test
mysql> LOAD DATA INFILE '/tmp/bit_test.txt'
       INTO TABLE bit_test (@var1)
       SET b = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-3), 2, 10) AS UNSIGNED);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT BIN(b+0) FROM bit_test;
+----------+
| BIN(b+0) |
+----------+
| 10       |
| 1111111  |
+----------+
2 rows in set (0.00 sec)

对于使用 0b 二进制表示法(例如,0b011010)的 BIT 值,请改用以下 SET 子句去掉前导 0b

SET b = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-2), 2, 10) AS UNSIGNED)

分区表支持

LOAD DATA 支持使用 PARTITION 子句进行显式分区选择,该子句带有一个或多个以逗号分隔的分区、子分区或两者兼有的名称列表。使用此子句时,如果文件中的任何行无法插入到列表中命名的任何分区或子分区中,则该语句将失败,并显示错误 找到与给定分区集不匹配的行。有关更多信息和示例,请参阅第 26.5 节“分区选择”

并发注意事项

使用 LOW_PRIORITY 修饰符,LOAD DATA 语句的执行将被延迟,直到没有其他客户端从表中读取数据。这只会影响使用表级锁定的存储引擎(例如 MyISAMMEMORYMERGE)。

使用 CONCURRENT 修饰符和满足并发插入条件的 MyISAM 表(即,它在中间不包含空闲块),其他线程可以在 LOAD DATA 执行时从表中检索数据。此修饰符会稍微影响 LOAD DATA 的性能,即使没有其他线程同时使用该表。

语句结果信息

LOAD DATA 语句完成后,它将返回以下格式的信息字符串

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

当使用 INSERT 语句插入值时,会出现与警告相同的情况(请参阅第 15.2.7 节“INSERT 语句”),但 LOAD DATA 在输入行中的字段过多或过少时也会生成警告。

您可以使用 SHOW WARNINGS 获取前 max_error_count 个警告的列表,作为有关出错信息的列表。请参阅第 15.7.7.41 节“SHOW WARNINGS 语句”

如果您使用的是 C API,则可以通过调用 mysql_info() 函数来获取有关该语句的信息。请参阅mysql_info()

复制注意事项

LOAD DATA 被认为对于基于语句的复制不安全。如果您将 LOAD DATAbinlog_format=STATEMENT 一起使用,则要应用更改的每个副本都会创建一个包含数据的临时文件。此临时文件未加密,即使源上启用了二进制日志加密也是如此,如果需要加密,请改用基于行或混合的二进制日志记录格式,因为副本不会为其创建临时文件。有关 LOAD DATA 和复制之间交互的更多信息,请参阅第 19.5.1.19 节“复制和 LOAD DATA”

其他主题

在 Unix 上,如果您需要 LOAD DATA 从管道读取数据,则可以使用以下技术(该示例将 / 目录的列表加载到表 db1.t1 中)

mkfifo /mysql/data/db1/ls.dat
chmod 666 /mysql/data/db1/ls.dat
find / -ls > /mysql/data/db1/ls.dat &
mysql -e "LOAD DATA INFILE 'ls.dat' INTO TABLE t1" db1

在这里,您必须运行生成要加载的数据的命令和 mysql 命令,无论是在单独的终端上,还是在后台运行数据生成过程(如上例所示)。如果不这样做,管道将阻塞,直到 mysql 进程读取数据。