MySQL โหลดค่า NULL จากข้อมูล CSV


167

ฉันมีไฟล์ที่สามารถมีคอลัมน์ตั้งแต่ 3 ถึง 4 คอลัมน์ของค่าตัวเลขซึ่งคั่นด้วยเครื่องหมายจุลภาค เขตข้อมูลว่างถูกกำหนดด้วยข้อยกเว้นเมื่อพวกเขาอยู่ในตอนท้ายของแถว:

1,2,3,4,5
1,2,3,,5
1,2,3

ตารางต่อไปนี้ถูกสร้างขึ้นใน MySQL:

+ ------- + -------- + ------ + ----- + --------- + ------- +
| ฟิลด์ | ประเภท | ว่างเปล่า คีย์ | เริ่มต้น | พิเศษ |
+ ------- + -------- + ------ + ----- + --------- + ------- +
| หนึ่ง | int (1) | ใช่ | | NULL | |
| สอง | int (1) | ใช่ | | NULL | |
| สาม | int (1) | ใช่ | | NULL | |
| สี่ | int (1) | ใช่ | | NULL | |
| ห้า | int (1) | ใช่ | | NULL | |
+ ------- + -------- + ------ + ----- + --------- + ------- +

ฉันพยายามโหลดข้อมูลโดยใช้คำสั่ง MySQL LOAD:

LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo FIELDS 
TERMINATED BY "," LINES TERMINATED BY "\n";

ตารางผลลัพธ์:

+ + ------ ------ ------- + + + ------ ------ +
| หนึ่ง | สอง | สาม | สี่ | ห้า |
+ + ------ ------ ------- + + + ------ ------ +
| 1 | 2 | 3 | 4 | 5 |
| 1 | 2 | 3 | 0 | 5 |
| 1 | 2 | 3 | NULL | NULL |
+ + ------ ------ ------- + + + ------ ------ +

ปัญหาอยู่ที่ความจริงที่ว่าเมื่อเขตข้อมูลว่างเปล่าในข้อมูลดิบและไม่ได้กำหนดไว้ MySQL ด้วยเหตุผลบางอย่างไม่ได้ใช้ค่าเริ่มต้นคอลัมน์ (ซึ่งเป็นค่า NULL) และใช้ศูนย์ ค่า NULL ถูกใช้อย่างถูกต้องเมื่อไม่มีฟิลด์ทั้งหมด

น่าเสียดายที่ฉันต้องแยกความแตกต่างระหว่าง NULL และ 0 ในขั้นตอนนี้ดังนั้นความช่วยเหลือใด ๆ จะได้รับการชื่นชม

ขอบคุณ S.

แก้ไข

ผลลัพธ์ของ SHOW WARNINGS:

+ --------- + ------ + -------------------------------- ------------------------ +
| ระดับ | รหัส | ข้อความ |
+ --------- + ------ + -------------------------------- ------------------------ +
| คำเตือน | 1366 | ค่าจำนวนเต็มไม่ถูกต้อง: '' สำหรับคอลัมน์ 'สี่' ที่แถว 2 |
| คำเตือน | 1261 | แถว 3 ไม่มีข้อมูลสำหรับคอลัมน์ทั้งหมด |
| คำเตือน | 1261 | แถว 3 ไม่มีข้อมูลสำหรับคอลัมน์ทั้งหมด |
+ --------- + ------ + -------------------------------- ------------------------ +

กับการเปลี่ยนแปลงสคีข้อมูลเช่นที่ผมจะใช้d6tstackLOAD DATAซึ่งสอดคล้องคอลัมน์ทั้งหมดก่อนที่จะใช้ ดูส่วนd6tstack ตัวอย่าง SQLเกี่ยวกับการเปลี่ยนแปลงคีมาข้อมูล
citynorman

คำตอบ:


193

สิ่งนี้จะทำในสิ่งที่คุณต้องการ มันอ่านฟิลด์ที่สี่เป็นตัวแปรท้องถิ่นแล้วตั้งค่าฟิลด์จริงเป็น NULL หากตัวแปรโลคัลสิ้นสุดที่มีสตริงว่าง:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(one, two, three, @vfour, five)
SET four = NULLIF(@vfour,'')
;

หากพวกเขาอาจว่างเปล่าทั้งหมดคุณจะต้องอ่านพวกเขาทั้งหมดเป็นตัวแปรและมีคำสั่ง SET หลายชุดดังนี้:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(@vone, @vtwo, @vthree, @vfour, @vfive)
SET
one = NULLIF(@vone,''),
two = NULLIF(@vtwo,''),
three = NULLIF(@vthree,''),
four = NULLIF(@vfour,'')
;

ในทางทฤษฎีแล้วฉันคิดว่า - แต่มันอยู่ในความทรงจำและเก็บข้อมูลเพียงเล็กน้อยต่อแถวดังนั้นฉันจึงนึกภาพว่ามันจะน้อยมาก แต่คุณควรทดสอบถ้าคุณคิดว่ามันอาจมีปัญหา
Duncan Lock

4
ฉันชอบคำตอบนี้จริงๆ ผู้ใช้สามารถเห็นสตริงว่าง''เมื่อพวกเขาดาวน์โหลด csv (ใช้IFNULL(Col,'')ในSELECT INTO OUTFILEแบบสอบถาม) สำหรับ excel แต่จากนั้นการอัปโหลดยอมรับว่าเป็นโมฆะและต้องจัดการกับ\Nใน csv ขอบคุณ!
chrisan

9
สำหรับวันที่ฉันใช้ 'NULLIF (STR_TO_DATE (@ date1, "% d /% m /% Y"), "0000-00-00")'
Joaquín L. Robles

1
ฉันมีไฟล์ csv ที่มีค่าศูนย์0ที่ควรแปลงเป็นNULL(เพราะเป็นไปไม่ได้ที่จะมีค่าศูนย์สำหรับข้อมูลที่เป็นปัญหา) และสตริงว่าง จะแน่ใจได้อย่างไรว่าทั้งศูนย์และสตริงว่างจะถูกแปลงเป็นNULL?
Paul Rougieux

nullif(@vone, 0)หากค่าศูนย์และสตริงที่ว่างเปล่าอยู่ในคอลัมน์ที่แยกต่างหากจากนั้นก็ทำข้างต้นสำหรับสตริงว่างเปล่าและบางอย่างเช่นนี้สำหรับศูนย์นี้:
Duncan Lock

136

คู่มือ MySQLพูดว่า:

เมื่ออ่านข้อมูลด้วย LOAD DATA INFILE คอลัมน์ว่างหรือหายไปจะถูกอัพเดตด้วย '' หากคุณต้องการค่า NULL ในคอลัมน์คุณควรใช้ \ N ในไฟล์ข้อมูล คำที่แท้จริง“ NULL” อาจถูกใช้ในบางสถานการณ์

ดังนั้นคุณต้องเปลี่ยนช่องว่างด้วย \ N ดังนี้:

1,2,3,4,5
1,2,3,\N,5
1,2,3

3
ขอบคุณสำหรับเคล็ดลับ - ฉันสงสัยว่าจะแก้ไขแหล่งข้อมูลดิบ แต่ถ้านี่เป็นวิธีเดียวที่อยู่รอบตัวฉันจะลองทำดู
Spiros

7
ฉันเข้าใจความสงสัยของคุณไม่มีใครชอบแก้ไขข้อมูลดิบมันแค่รู้สึกไม่ถูกต้อง อย่างไรก็ตามถ้าคุณคิดถึงมันเป็นเวลาหนึ่งนาทีจะต้องมีวิธีที่จะแยกแยะความแตกต่างระหว่าง NULL และสตริงว่าง หากรายการว่างถูกแปลเป็น NULL คุณต้องมีลำดับพิเศษสำหรับสตริงว่าง มันจะดีที่มีวิธีการบอก MySQL วิธีการจัดการกับรายการว่างเปล่า แต่บางสิ่งบางอย่างเช่นโหลดข้อมูล INFILE '/tmp/testdata.txt' ลงในตารางหมู่ MRE รักษา BLANKS เป็นโมฆะ ...
มิถุนายน

2
OK แต่ถ้าคุณมีFields enclosed by: "คือว่า"\N"ของ"name",\N,"stuff"
Jonathon

3
ฉันสามารถตรวจสอบได้ว่าอย่างน้อยสำหรับ "phpMyAdmin 3.5.5" ไม่\NยอมรับรูปแบบการแสดงNULLว่า ใช้แทนNULLเหมือนในตัวอย่างนี้:"name","age",NULL,"other","stuff"
Jonathon

1
เรามี MySQL 5.5.46-0 + deb8u1 ฉันลองทั้ง NULL และ \ N และมีเพียง \ N เท่านั้นที่ทำงานให้เรา
raphael75

6

พฤติกรรมจะแตกต่างกันไปขึ้นอยู่กับการกำหนดค่าฐานข้อมูล ในโหมดเข้มงวดสิ่งนี้จะทำให้เกิดข้อผิดพลาดเป็นคำเตือน อาจใช้แบบสอบถามต่อไปนี้เพื่อระบุการกำหนดค่าฐานข้อมูล

mysql> show variables like 'sql_mode';

ขอบคุณ! ฉันเกาหัวของฉันพยายามหาเหตุผลว่าทำไมการนำเข้า CSV ด้วยคอลัมน์ว่างเปล่าฉันจึงนำเข้าเรียบร้อยแล้วบนเซิร์ฟเวอร์ที่ใช้งานจริงเมื่อวานนี้ไม่ได้ทำงานในการติดตั้งใหม่เอี่ยมของฉัน - นี่คือคำตอบในกรณีของฉัน!
Emma Burrows

3

ประมวลผลอินพุต CSV ของคุณล่วงหน้าเพื่อแทนที่รายการว่างด้วย \ N

พยายามที่ regex: s / ,, /, \ n, / g และ s /, $ /, \ N / g

โชคดี.


1
Regex นี้ใช้งานได้บางส่วนไม่สามารถแก้ไขรายการว่างที่เรียงตามลำดับเช่น ,,,, จะเป็น \ n ,, \ n ควรใช้งานได้หากคุณเรียกใช้สองครั้ง
ievgen

1
จะสรุปคำตอบและความคิดเห็นก่อนหน้า ตามมาทำงานให้ฉันตามลำดับ: sed -i 's / ,, /, \ N / g' $ file, sed -i 's / ,, /, / g' $ file, sed -i 's / \ N, $ / \ N / g '$ file,
Omar Khazamov

ฉันต้องการทำสิ่งนี้ แต่ฉันไม่ชัดเจนว่าคุณใช้งาน regex นี้อย่างไร หากคุณใช้ MySQL เพื่อรันไฟล์นี้สิ่งนี้จะเป็นทางออกที่ดีที่สุด แต่คุณไม่พูดและฉันไม่ต้องการใช้เวลาหลายครั้งในการทำสิ่งที่อาจเป็นไปไม่ได้
DonkeyKong


0

แสดงตัวแปร

Show variables like "`secure_file_priv`";

หมายเหตุ: เก็บไฟล์ csv ของคุณในตำแหน่งที่กำหนดโดยคำสั่งดังกล่าว

create table assessments (course_code varchar(5),batch_code varchar(7),id_assessment int, assessment_type varchar(10), date int , weight int);

หมายเหตุ: ที่นี่dateคอลัมน์ '' มีค่าว่างในไฟล์ csv

LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/assessments.csv' 
INTO TABLE assessments
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '' 
LINES TERMINATED BY '\n' 
IGNORE 1 ROWS 
(course_code,batch_code,id_assessment,assessment_type,@date,weight)
SET date = IF(@date = '', NULL, @date);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.