MySQL ดีกว่าที่จะแทรก NULL หรือสตริงว่าง?


230

ฉันมีแบบฟอร์มบนเว็บไซต์ที่มีฟิลด์ต่าง ๆ มากมาย ฟิลด์บางฟิลด์เป็นทางเลือกในขณะที่บางฟิลด์บังคับ ในฐานข้อมูลของฉันฉันมีตารางที่เก็บค่าเหล่านี้ทั้งหมดเป็นวิธีที่ดีกว่าหรือไม่ในการแทรกค่า NULL หรือสตริงว่างลงในคอลัมน์ DB ที่ผู้ใช้ไม่ได้ใส่ข้อมูลใด ๆ

คำตอบ:


220

โดยใช้NULLคุณสามารถแยกความแตกต่างระหว่าง "ใส่ข้อมูล" และ "ใส่ข้อมูลที่ว่างเปล่า"

ความแตกต่างบางอย่างเพิ่มเติม:

  • LENGTHของNULLเป็นNULLเป็นของสตริงที่ว่างเปล่าเป็นLENGTH0

  • NULLs จะถูกจัดเรียงก่อนสตริงว่าง

  • COUNT(message)จะนับสตริงว่าง แต่ไม่ใช่NULLs

  • คุณสามารถค้นหาสตริงที่ว่างเปล่าใช้ตัวแปรที่ถูกผูกไว้ NULLแต่ไม่ได้สำหรับ แบบสอบถามนี้:

    SELECT  *
    FROM    mytable 
    WHERE   mytext = ?

    จะไม่ตรงกับNULLในmytextสิ่งที่คุ้มค่าที่คุณส่งผ่านจากลูกค้า ในการจับคู่NULLคุณจะต้องใช้ข้อความค้นหาอื่น ๆ :

    SELECT  *
    FROM    mytable 
    WHERE   mytext IS NULL

3
แต่อันไหนที่คุณคิดว่าเร็วกว่ากัน? 0 หรือ NULL หรือ ""
Atul Dravid

8
ใน InnoDB NULL ใช้พื้นที่น้อย
Timo Huovinen

37
ฉันคิดว่านี่เป็นคำตอบที่ถูก แต่มันก็ไม่สนใจองค์ประกอบ "แนวปฏิบัติที่ดีที่สุด" ของคำถามและเน้นไปที่ข้อเท็จจริงที่เกี่ยวข้องกันโดยเรียงตามลำดับ (ลำดับการจัดเรียง NULL และความยาว? สำหรับประเภทการป้อนข้อมูลข้อความส่วนใหญ่ไม่มีความแตกต่างระหว่าง "ไม่มีการตอบสนอง" และ "การตอบสนองที่ว่างเปล่า" ดังนั้นฉันคิดว่านี่เป็นคำถามที่ดีที่สมควรได้รับคำตอบที่ดีกว่า
Nick

6
NULL ยังทำงานได้ดีเมื่อตั้งค่าฟิลด์ UNIQUE ตัวอย่างเช่นหากคุณมีฟิลด์เช่นใบขับขี่เพื่อเพิ่มหมายเลข DL ของบุคคลและผู้ชายไม่มี เนื่องจากเป็นฟิลด์ที่ไม่ซ้ำใครคนแรกที่ไม่มีหมายเลข DL จะถูกเพิ่ม แต่ไม่ใช่ฟิลด์ถัดไปเนื่องจากจะทำให้เกิดข้อผิดพลาดของข้อ จำกัด ที่ไม่ซ้ำกัน ดังนั้น NULL จะดีกว่า
Saifur Rahman Mohsin

1
@Quassnoi อ่า ... ฉันหมายความว่าทำไมมันเป็นวิธีปฏิบัติที่ไม่ถูกต้องในการตั้งค่าใบขับขี่หมายเลขเป็นเอกลักษณ์ ... ?
cedbeu

44

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


11
สิ่งนี้ฟังดูเหลือเชื่อสำหรับฉันแม้แต่ในลิงก์ของคุณดังนั้นฉันจึงลอง ฟิลด์ Null, ตั้งค่าเป็น '', oracle จะไม่สนใจมัน รายงานความยาวเป็นโมฆะมากกว่า 0 นั่นเป็นความผิดพลาด จะต้องมีวิธีการประมาณนี้ คิดว่าฉันจะโพสต์สิ่งนี้เป็นคำถามอื่น
Steve B.

1
Steve B.: ดูคำถามนี้: stackoverflow.com/questions/1171196/…
Quassnoi

ขอบคุณสำหรับการอ้างอิงถึงแม้ว่าฉันยังไม่เข้าใจเหตุผล โพสต์เป็นstackoverflow.com/questions/1268177/…
Steve B.

อาจมีค่าอัปเดตคำตอบเพื่อรวมข้อมูลจากลิงค์โพสต์โดย Quassnoi
SamuelKDavis

7
Peoplesoft (with Oracle DB) ใช้ช่องว่างเดียวเพื่อระบุค่าว่าง โง่อย่างไม่น่าเชื่อ พวกเขายังใช้ 0.00025 เพื่อระบุ 0 สำหรับ FTE เนื่องจากไม่อนุญาต 0 ตัวเลือกที่น่ารักถูกสร้างขึ้นในผลิตภัณฑ์นั้น
JP Duffy

9

สิ่งหนึ่งที่ต้องจำไว้คือ NULL อาจทำให้ codepath ของคุณยากขึ้น ในหลามตัวอย่างส่วนใหญ่อะแดปเตอร์ฐานข้อมูล / ORMs แผนที่จะNULLNone

ดังนั้นสิ่งที่ชอบ:

print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow

อาจส่งผลให้ "Hello, None Joe Doe!" หากต้องการหลีกเลี่ยงคุณต้องมีรหัสเช่นนี้:

if databaserow.title:
    print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
    print "Hello, %(firstname) %(lastname)!" % databaserow

ซึ่งสามารถทำให้สิ่งต่าง ๆ มีความซับซ้อนมากขึ้น


25
ในความคิดของฉันเหยียดหยามฐานข้อมูลของคุณเพื่อ "แก้ไข" ข้อผิดพลาดในรหัสของคุณหรือกรอบการทำงานคือการเขียนโค้ดที่แย่มาก เมื่อไม่มีข้อมูลคุณควรแทรก NULL และสอดคล้องในการใช้ มิฉะนั้นคุณต้องใช้ข้อความเช่น: if (myString == null || myString = "") เมื่อวัตถุไม่ได้ตั้งค่าหรือกำหนดไว้ในรหัสของคุณคุณก็ใช้ NULL แทน "ตัวยึด" บางชนิด (ซึ่งสตริงว่างอยู่ในความคิดของฉัน)
Gertjan

5
ขึ้นอยู่กับภาษาที่คุณเลือกเป็นอย่างมาก ใน Python "ถ้าไม่ใช่ myString:" จะทดสอบไม่มีและ "" อาจเป็นปัญหาทางวัฒนธรรมเป็นหลัก Java Guys "การปฏิบัติที่ไม่ดี" คือความสง่างามของบุคคลที่มีพลัง
สูงสุด

9

ดีกว่าที่จะแทรกNULLสำหรับความสอดคล้องในฐานข้อมูลของคุณใน MySQL กุญแจต่างประเทศสามารถเก็บไว้ได้NULLแต่ไม่ใช่สตริงว่างเปล่า

คุณจะมีปัญหากับสตริงว่างในข้อ จำกัด คุณอาจต้องแทรกระเบียนปลอมด้วยสตริงว่างที่ไม่ซ้ำกันเพื่อตอบสนองข้อ จำกัด Foreign Key การปฏิบัติที่ไม่ดีฉันเดา

ดูเพิ่มเติมที่: foreign key สามารถเป็นค่า NULL และ / หรือทำซ้ำได้หรือไม่?


ปัญหาข้อ จำกัด ทำให้ฉันสะดุดในอดีตดังนั้นฉันจึง "+1" ตอบคำถามนี้
HPWD

แต่ถ้าคุณใช้ NULL ตรวจสอบให้แน่ใจว่าคุณไม่เคยจบด้วยสตริงที่ว่างเปล่าเช่นกัน ใช้งานง่ายด้วยเทคโนโลยี UI มากมาย
Tuntable

5

ฉันไม่ทราบว่าวิธีปฏิบัติที่ดีที่สุดจะอยู่ที่นี่ แต่โดยทั่วไปแล้วฉันมักจะผิดพลาดหากไม่ต้องการให้ null หมายถึงสิ่งที่แตกต่างจากสตริงว่างและการป้อนข้อมูลของผู้ใช้ตรงกับนิยามสตริงว่างเปล่าของคุณ

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

โอ้และพึงระลึกไว้ว่าหากคอลัมน์นั้นเป็นโมฆะเรคคอร์ดจะมีโอกาสน้อยที่จะปรากฏในคิวรีใด ๆ ที่เลือก (มีส่วนคำสั่งในเงื่อนไข SQL) ที่อยู่นอกคอลัมน์นั้นยกเว้นการเลือกนั้นจะเป็นคอลัมน์ว่าง แน่นอน.


1
... และตอนนี้ฉันเห็นคำตอบข้างบนฉันฉันคิดว่ามันปลอดภัยที่จะบอกว่าความแตกต่างตามปกติที่คุณสนใจคือไม่มีข้อมูลเทียบกับข้อมูลที่ว่างเปล่า :-)
Platinum Azure

1

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

คอลัมน์ใน INDEX ที่ไม่ซ้ำใคร:
(event_type_id, event_title, วันที่, สถานที่, URL)

ตัวอย่าง 1:
(1, 'BBQ', '2018-07-27', null, null)
(1, 'BBQ', '2018-07-27', null, null) // อนุญาตและทำซ้ำ

ตัวอย่าง 2:
(1, 'BBQ', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // ไม่ได้รับอนุญาตเนื่องจากมีการทำซ้ำ

นี่คือรหัสบางส่วน:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `event_title` varchar(50) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `location` varchar(50) DEFAULT NULL,
  `url` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

ตอนนี้แทรกสิ่งนี้เพื่อดูว่าจะอนุญาตแถวที่ซ้ำกัน:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);

ตอนนี้แทรกและตรวจสอบว่ามันไม่ได้รับอนุญาต:

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`, 
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');

ดังนั้นไม่มีถูกหรือผิดที่นี่ ขึ้นอยู่กับคุณตัดสินใจว่าอะไรดีที่สุดกับกฎเกณฑ์ทางธุรกิจของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.