MySQL, CSV verilerinden NULL değerler yükler


167

Virgülle ayrılmış sayısal değerler 3 ila 4 sütun içeren bir dosya var. Boş alanlar, satırın sonunda olduklarında istisna olarak tanımlanır:

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

MySQL'de aşağıdaki tablo oluşturuldu:

+ ------- + -------- + ------ + ----- + --------- + ------- +
| Alan | Türü | Boş | Anahtar | Varsayılan | Ekstra |
+ ------- + -------- + ------ + ----- + --------- + ------- +
| bir | int (1) | EVET | | NULL | |
| iki | int (1) | EVET | | NULL | |
| üç | int (1) | EVET | | NULL | |
| dört | int (1) | EVET | | NULL | |
| beş | int (1) | EVET | | NULL | |
+ ------- + -------- + ------ + ----- + --------- + ------- +

MySQL LOAD komutunu kullanarak veri yüklemeye çalışıyorum:

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

Ortaya çıkan tablo:

+ ------ + ------ + ------- + ------ + ------ +
| bir | iki | üç | dört | beş |
+ ------ + ------ + ------- + ------ + ------ +
| 1 | 2 | 3 | 4 | 5 |
| 1 | 2 | 3 | 0 | 5 |
| 1 | 2 | 3 | NULL | NULL |
+ ------ + ------ + ------- + ------ + ------ +

Sorun, ham verilerde bir alan boş olduğunda ve tanımlanmadığında, MySQL'in bir nedenden ötürü varsayılan sütun değerlerini (NULL) kullanmaması ve sıfır kullanmasıdır. Alan tamamen eksik olduğunda NULL doğru kullanılır.

Ne yazık ki, bu aşamada NULL ve 0'ı ayırt edebilmeliyim, böylece herhangi bir yardım takdir edilecektir.

Teşekkürler S.

Düzenle

SHOW UYARILARI çıkışı:

+ --------- + ------ + -------------------------------- ------------------------ +
| Seviye | Kodu | Mesaj |
+ --------- + ------ + -------------------------------- ------------------------ +
| Uyarı | 1366 | Yanlış tamsayı değeri: '' satır 2'deki 'dört' sütunu için |
| Uyarı | 1261 | Satır 3 tüm sütunlar için veri içermiyor |
| Uyarı | 1261 | Satır 3 tüm sütunlar için veri içermiyor |
+ --------- + ------ + -------------------------------- ------------------------ +

Böyle veri şeması değişiklikleri ile çalıştırmadan önce tüm sütunları hizalar d6tstack kullanmak istiyorsunuzLOAD DATA . Veri şeması değişiklikleriyle ilgili d6tstack SQL örnekleri bölümüne bakın .
citynorman

Yanıtlar:


193

Bu istediğinizi yapar. Dördüncü alanı yerel bir değişkene okur ve yerel değişken boş bir dize içeriyorsa, gerçek alan değerini NULL olarak ayarlar:

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,'')
;

Eğer hepsi boşsa, hepsini değişkenlere okur ve aşağıdaki gibi birden fazla SET deyimine sahip olursunuz:

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,'')
;

Teorik olarak, sanırım - ama hepsi bellekte ve satır başına sadece küçük miktarlarda veri tutarak, bu yüzden sonsuz olacağını hayal ediyorum; ancak bunun bir sorun olabileceğini düşünüyorsanız test etmelisiniz.
Duncan Lock

4
Bu cevabı gerçekten çok beğendim. Kullanıcılar boş dizeleri görebilirsiniz ''onlar (kullanarak bir csv indirdiğinizde IFNULL(Col,'')içinde SELECT INTO OUTFILEexcel için sorguda) ama sonra yüklemeler ile uğraşmak zorunda vs boş olarak kabul \Ncsv. Teşekkürler!
chrisan

9
tarihler için 'NULLIF (STR_TO_DATE (@ tarih1, "% d /% m /% Y"), "0000-00-00")' kullandım
Joaquín L. Robles

1
0Dönüştürülmesi gereken sıfırlar içeren bir csv dosyası var NULL(çünkü söz konusu veriler için sıfır değerine sahip olmak mümkün değildir) ve aynı zamanda boş dizeleri. Hem sıfırların hem de boş dizelerin dönüştürüldüğünden nasıl emin olunur NULL?
Paul Rougieux

Sıfır değerler ve boş dizeler ayrı sütunlarda ise, o zaman sadece boş dizeler için yukarıdaki yapmak, ve sıfırlar için böyle bir şey: nullif(@vone, 0).
Duncan Lock

136

MySQL kılavuzu diyor:

LOAD DATA INFILE ile veri okurken, boş veya eksik sütunlar '' ile güncellenir. Bir sütunda NULL değeri istiyorsanız, veri dosyasında \ N kullanmalısınız. Gerçek kelimesi “NULL” bazı durumlarda da kullanılabilir.

Bu yüzden boşlukları şöyle \ N ile değiştirmeniz gerekir:

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

3
Bahşiş için teşekkürler - Ham kaynak verilerini düzenlemek için şüpheliyim, ancak bu tek yol ise bunu deneyeceğim.
Spiros

7
Şüpheciliğinizi anlıyorum, hiç kimse ham verileri düzenlemeyi sevmiyor, doğru hissetmiyor. Ancak, bir dakika düşünürseniz, NULL ve boş dize arasında ayrım yapmanın bir yolu olmalı. Boş girişler NULL değerine çevrilirse, boş dize için özel bir sıraya ihtiyacınız olacaktır. Bu nasıl nasıl boş giriş rağmen, TABLO moo MUAMELE BLANKS AS NULL INTO LOAD DATA INFILE '/tmp/testdata.txt' gibi bir şey tedavi etmek MySQL anlatmak için bir yol olsa güzel olurdu olurdu ...
Janci

2
Eğer varsa Tamam, ama Fields enclosed by: "olmasıdır "\N"arasında"name",\N,"stuff"
Jonathon

3
En azından "phpMyAdmin 3.5.5" için hiçbir stilin ifade \Nolarak kabul edilmediğini doğrulayabilirim NULL. Bunun yerine NULL, bu örnekte olduğu gibi kullanın :"name","age",NULL,"other","stuff"
Jonathon

1
MySQL 5.5.46-0 + deb8u1 var. Hem NULL hem de \ N denedim ve sadece \ N bizim için çalıştı.
raphael75

6

Davranış veritabanı yapılandırmasına bağlı olarak farklıdır. Katı modda bu, başka bir hata uyarısı verir. Veritabanı yapılandırmasını tanımlamak için aşağıdaki sorgu kullanılabilir.

mysql> show variables like 'sql_mode';

Teşekkürler! Dün üretim sunucusuna başarıyla ithal ettiğim boş sütunlarla bir CSV'yi içe aktarmanın neden yepyeni yerel kurulumum üzerinde çalışmadığını anlamaya çalışarak başımı kaşıyordum - bu benim durumumdaki cevaptı!
Emma Burrows

3

Boş girişleri \ N ile değiştirmek için CSV girişinizi önceden işleyin.

Bir normal ifadeyi deneyin: s / ,, /, \ n, / g ve s /, $ /, \ N / g

İyi şanslar.


1
Bu normal ifade kısmen işe yarıyor, sıralı boş girişleri çözmüyor, örneğin ,,,, olacak, \ n ,, \ n, İki kez çalıştırırsanız kullanılabilir olmalı
ievgen

1
Cevabı ve önceki yorumu özetleyecektir. Aşağıdaki benim için çalıştı: sed -i 's / ,, /, \ N / g' $ dosya, sed -i 's / ,, /, / g' $ dosya, sed -i 's / \ N, $ / \ N / g '$ dosya,
Omar Khazamov

Bunu yapmak istiyorum, ama bu normal ifadeyi nasıl çalıştırdığınız konusunda net değilim. Dosyaya karşı çalıştırmak için MySQL kullanıyorsanız, bu en iyi çözüm olacaktır. Ama siz söylemiyorsunuz ve mümkün olmayan bir şeyin nasıl yapılacağını araştırarak bir sürü zaman harcamak istemiyorum.
DonkeyKong

1

(değişken1, @ değişken2, ..) SET değişken2 = nullif (@ değişken2, '' veya '') >> herhangi bir koşul koyabilirsiniz


0

değişkenleri göster

Show variables like "`secure_file_priv`";

Not: csv dosyanızı yukarıdaki komutla verilen konumda tutun.

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

Not: ' date' sütununda csv dosyasında bazı boş değerler vardır.

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.