2015-03-26 2 views
2

У меня странное поведение с SELECT INTO OUFILE, и я не нашел ответа.Mysql INTO OUTFILE Вложенные объединения с NULL, вызывающие проблему форматирования с целым числом

Чтобы возобновить У меня есть таблица вроде этого:

CREATE TABLE `mytable` (
    `id` int(11) NOT NULL auto_increment, 
    `field1` decimal(10,2) default NULL, 
    `field2` int(11) default NULL, 
    `field3` tinyint(4) default NULL, 
    PRIMARY KEY (`id`), 
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Когда я выполнить запрос так:

SELECT * INTO OUTFILE '/tmp/output.dat' 
FIELDS TERMINATED BY '|' 
OPTIONALLY ENCLOSED BY '\"' 
ESCAPED BY '' 
LINES TERMINATED BY '\n' 
FROM mytable; 

я получить результат, как это в output.dat:

"12345678"|"20.00^@^@^@^@^@^@^@"|"1426513906^@"|"0^@^@^@" 
"95863214"|"20.00^@^@^@^@^@^@^@"|"1426514075^@"|"1^@^@^@" 

без ESCAPED BY:

SELECT * INTO OUTFILE '/tmp/output.dat' 
FIELDS TERMINATED BY '|' 
OPTIONALLY ENCLOSED BY '\"' 
LINES TERMINATED BY '\n' 
FROM mytable; 

У меня есть результат, как эти:

"12345678"|"20.00\0\0\0\0\0\0\0"|"1426513906\0"|"0\0\0\0" 
"95863214"|"20.00\0\0\0\0\0\0\0"|"1426514075\0"|"1\0\0\0" 

Mysql среда:

"protocol_version";"10" 
"version";"5.0.67-community-log" 
"version_comment";"MySQL Community Edition (GPL)" 
"version_compile_machine";"x86_64" 
"version_compile_os";"redhat-linux-gnu" 

Это кажется, что MySQL пытается заполнить с этим специальными символами, чтобы иметь размер, установленный в структуре из мыла. С TRIM У меня нет этих символов. Но я хочу знать, нормально ли иметь такое поведение только с целым числом и десятичным или это ошибка? Я также хочу знать, есть ли другое решение, чтобы избежать использования TRIM с каждым полем? Потому что у меня много запросов более сложный, чем этот.

Спасибо за вашу помощь и время, которое вы приняли, чтобы прочитать мой пост

С уважением

EDIT: Я думал, что проблема, вероятно, происходит от INTO OUFILE и только поля типа. В этом случае я не думал упоминать вложенные союзы. Поэтому я изменил название, и я отвечаю на свой вопрос.

+0

Это не причина. Но вы указали на ошибку, которую я сделал, когда я написал этот пост. Я скопировал/вставил неправильный запрос. Теперь он правильный. Спасибо за ваш комментарий. – Mansour

+0

Хорошо, все еще только FYI, я не могу воспроизвести это поведение с 5.6.20. И я не помню, чтобы когда-либо было такое поведение с предыдущими версиями. Как вы оцениваете результат? Возможно, это не проблема MySQL, а ваш редактор/оболочка. – fancyPants

+0

Я использую linux editor vi. Это не редактор. У меня есть предупреждения, такие как «_Data усечено для столбца« field1 »в строке 1_», когда я пытаюсь загрузить данные такого типа. Редактировать: Я просто заметил, что у меня нет такого поведения с первичным ключом! Странный!? – Mansour

ответ

0

Последнее редактирование:Чтобы возобновить, самое лучшее найденное решение, чтобы заставить бежать с обратной косой черты и не оставить его пустым:

SELECT * INTO OUTFILE '/tmp/output1.dat' 
FIELDS TERMINATED BY '|' 
ENCLOSED BY '\"' 
ESCAPED BY '\\' 
LINES TERMINATED BY '\n' 
FROM 
    ((SELECT 
    id_test, 
    field2, 
    field3 
    FROM mytable1) 

    UNION 

    (SELECT 
    * 
    FROM 
     ((SELECT 
     id_test, 
     field2, 
     NULL AS field3 
     FROM mytable2) 

     UNION 

     (SELECT 
     id_test, 
     NULL AS field2, 
     NULL AS field3 
     FROM mytable3) 
     ) test) 
    ) tmptable; 

Записки из mysql documentation:

Если FIELDS ESCAPED BY characte r пуст, никакие символы не экранируются и NULL выводится как NULL, not \ N. Вероятно, не очень хорошая идея: указать пустой escape-символ, особенно если значения полей в содержат ваши данные, содержащие любые символы только что приведенного списка.

....

Также обратите внимание, что если вы укажете пустое значение ESCAPED BY, то возможно непреднамеренно генерировать вывод, который не может быть правильно прочитан by LOAD DATA INFILE.

Предыдущие решения с объяснением:

Я нашел ответ на мою проблему. Он исходит из вложенных объединений с значениями NULL. Я объясню на примере, что это лучше, чем длинный разговор.

Здесь MySQL контекст:

DROP TABLE IF EXISTS `mytable1`; 

CREATE TABLE `mytable1` (
    `id_test` INT(11) NOT NULL AUTO_INCREMENT, 
    `field1` DECIMAL(10,2) DEFAULT NULL, 
    `field2` INT(11) DEFAULT NULL, 
    `field3` TINYINT(4) DEFAULT NULL, 
    PRIMARY KEY (`id_test`) 
) ENGINE=MYISAM AUTO_INCREMENT=95863215 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

/*Data for the table `mytable` */ 

INSERT INTO `mytable1`(`id_test`,`field1`,`field2`,`field3`) VALUES (12345678,20.00,1426513906,0),(95863214,20.00,1426514075,1); 

/*Table structure for table `mytable2` */ 

DROP TABLE IF EXISTS `mytable2`; 

CREATE TABLE `mytable2` (
    `id_test` INT(11) NOT NULL AUTO_INCREMENT, 
    `field1` DECIMAL(10,2) DEFAULT NULL, 
    `field2` INT(11) DEFAULT NULL, 
    PRIMARY KEY (`id_test`) 
) ENGINE=MYISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

/*Data for the table `mytable2` */ 

INSERT INTO `mytable2`(`id_test`,`field1`,`field2`) VALUES (1,25.00,12345),(2,11.00,52146); 

/*Table structure for table `mytable3` */ 

DROP TABLE IF EXISTS `mytable3`; 

CREATE TABLE `mytable3` (
    `id_test` INT(11) NOT NULL AUTO_INCREMENT, 
    `field1` DECIMAL(10,2) DEFAULT NULL, 
    `field3` TINYINT(4) DEFAULT NULL, 
    PRIMARY KEY (`id_test`) 
) ENGINE=MYISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

/*Data for the table `mytable3` */ 

INSERT INTO `mytable3`(`id_test`,`field1`,`field3`) VALUES (2,12.00,2),(4,23.00,31); 

И с окружающей средой:

"protocol_version";"10" 
"version";"5.0.67-community-log" 
"version_comment";"MySQL Community Edition (GPL)" 
"version_compile_machine";"x86_64" 
"version_compile_os";"redhat-linux-gnu" 

Или с этим один:

"protocol_version";"10" 
"version";"5.0.95-log" 
"version_bdb";"Sleepycat Software: Berkeley DB 4.1.24: (December 16, 2011)" 
"version_comment";"Source distribution" 
"version_compile_machine";"x86_64" 
"version_compile_os";"redhat-linux-gnu" 

Мы воспроизводим случай с такой запрос:

SELECT * INTO OUTFILE '/tmp/output1.dat' 
FIELDS TERMINATED BY '|' 
ENCLOSED BY '\"' 
ESCAPED BY '' 
LINES TERMINATED BY '\n' 
FROM 
    ((SELECT 
    id_test, 
    field2, 
    field3 
    FROM mytable1) 

    UNION 

    (SELECT 
    * 
    FROM 
     ((SELECT 
     id_test, 
     field2, 
     NULL AS field3 
     FROM mytable2) 

     UNION 

     (SELECT 
     id_test, 
     NULL AS field2, 
     NULL AS field3 
     FROM mytable3) 
     ) test) 
    ) tmptable; 

Мы получаем этот результат:

"12345678"|"1426513906"|"0^@^@^@" 
"95863214"|"1426514075"|"1^@^@^@" 
"1"|"12345"|NULL 
"2"|"52146"|NULL 
"2"|NULL|NULL 
"4"|NULL|NULL 

Когда мы выполняем тот же запрос с заменой последнего NULL с 1, например, или с удалением последнего союза:

SELECT * INTO OUTFILE '/tmp/output1.dat' 
FIELDS TERMINATED BY '|' 
ENCLOSED BY '\"' 
ESCAPED BY '' 
LINES TERMINATED BY '\n' 
FROM 
    ((SELECT 
    id_test, 
    field2, 
    field3 
    FROM mytable1) 

    UNION 

    (SELECT 
    * 
    FROM 
     ((SELECT 
     id_test, 
     field2, 
     NULL AS field3 
     FROM mytable2) 

     UNION 

     (SELECT 
     id_test, 
     NULL AS field2, 
     1 AS field3 
     FROM mytable3) 
     ) test) 
    ) tmptable; 

Мы получаем ожидаемый Rigth результат:

"12345678"|"1426513906"|"0" 
"95863214"|"1426514075"|"1" 
"1"|"12345"|NULL 
"2"|"52146"|NULL 
"2"|NULL|1 
"4"|NULL|1 

Это лишь простой пример без ГДЕ, чтобы объяснить. В моем случае вложенный союз используется, потому что у нас разные значения в разных условиях.

Так что будьте осторожны с вложенной UNION с NULL значения в случае экспорта с INTO OUTFILE. Для моего случая решение было вложенными объединениями предохранителей в одном запросе без UNION.

Обратите внимание, что я не воспроизвести этот случай с Mysql 5.6.23 MySQL Community Server на Windows 7.

Смежные вопросы