เมื่อใดที่จะใช้ NULL และเมื่อใช้สตริงว่าง?


82

ฉันสนใจ MySQL และ PostgreSQL เป็นส่วนใหญ่ แต่คุณสามารถตอบคำถามต่อไปนี้ได้โดยทั่วไป:

  • มีสถานการณ์ตรรกะที่จะเป็นประโยชน์ในการแยกสตริงว่างจาก NULL หรือไม่
  • สิ่งที่จะเป็นผลกระทบที่เก็บทางกายภาพสำหรับการจัดเก็บสตริงว่างเปล่าเป็น ...

    • โมฆะ?
    • สตริงว่างเปล่า
    • อีกสาขาหนึ่ง?
    • มีวิธีอื่นอีกไหม?

คำตอบ:


67

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

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


2
1 ฐานข้อมูลน้อยมากที่เคยต้องกังวลเกี่ยวกับความแตกต่างของความเร็ว / ขนาดของการใช้NULLหรือไม่
แพทริค

28
ตกลง ... ฉันพยายามจองค่า NULL เป็น 'ไม่เป็นที่รู้จัก' ... สตริงว่างคือ 'เรารู้ว่าควรจะว่างเปล่า' มีประโยชน์อย่างยิ่งเมื่อข้อมูลของคุณมาจากหลายแหล่ง
Joe

6
โดดเด่น - ไม่ทราบค่า NULL, ระบุสตริงว่างเปล่า
ScottCher

@ Larry ประสิทธิภาพการทำงานของสิ่งที่ส่งผลกระทบต่อ? ประสิทธิภาพแตกต่างกันอย่างไรกับตารางของคอลัมน์จำนวนมากเทียบกับตารางของหลายแถว
Shimmy

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

25

ฉันไม่รู้เกี่ยวกับ MySQL และ PostgreSQL แต่ให้ฉันทำสิ่งนี้โดยทั่วไป

มีหนึ่ง DBMS คือ Oracle ซึ่งไม่อนุญาตให้เลือกเป็นผู้ใช้ระหว่าง NULL และ '' สิ่งนี้แสดงให้เห็นอย่างชัดเจนว่าไม่จำเป็นต้องแยกแยะระหว่างทั้งสอง มีผลกระทบที่น่ารำคาญ:

คุณตั้งค่า varchar2 เป็นสตริงว่างเช่นนี้:

Update mytable set varchar_col = '';

สิ่งต่อไปนี้นำไปสู่ผลลัพธ์เดียวกัน

Update mytable set varchar_col = NULL;

แต่ในการเลือกคอลัมน์ที่ค่าว่างเปล่าหรือค่า NULL คุณต้องใช้

select * from mytable where varchar_col is NULL;

การใช้

select * from mytable where varchar_col = '';

ถูกต้องทางไวยากรณ์ แต่จะไม่ส่งกลับแถว

ในอีกด้านหนึ่งเมื่อเชื่อมสตริงใน Oracle NULL varchars ถือว่าเป็นสตริงว่าง

select NULL || 'abc' from DUAL;

อัตราผลตอบแทนabc DBMS อื่นจะคืนค่า NULL ในกรณีเหล่านี้

เมื่อคุณต้องการแสดงอย่างชัดเจนว่ามีการกำหนดค่าคุณต้องใช้บางอย่างเช่น ''

และคุณต้องกังวลว่าการตัดส่วนที่ไม่ว่างเปล่าเป็น NULL หรือไม่

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

มันทำ

ตอนนี้ดู DBMS โดยที่ '' ไม่เหมือนกับ NULL (เช่น SQL-Server)

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


เกี่ยวข้อง: stackoverflow.com/questions/203493/…
Joe

17

ขึ้นอยู่กับโดเมนที่คุณใช้งาน NULLหมายถึงการขาดค่า (เช่นไม่มีค่า ) ในขณะที่สตริงว่างหมายถึงมีค่าสตริงที่มีความยาวเป็นศูนย์

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


7
หากผู้ใช้เลือกที่จะไม่ระบุเพศคุณควรจัดเก็บ "ปฏิเสธที่จะให้บริการ" NULL คลุมเครือ นอกจากนี้ยังอาจหมายถึง "ลูกค้าไม่ได้ถูกถาม", "ลูกค้าระบุเพศที่ไม่อยู่ในรายชื่อของเรา" ฯลฯ
Jon of All Trades

8

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

นอกจากนี้ยังมีความแตกต่างบางอย่างกับพีชคณิตเชิงสัมพันธ์และค่า NULL: NULL! = NULL เป็นต้น


4
ไม่ใช่กรณีที่ NULL! = NULL เพราะนั่นเป็น NULL ;-)
Peter Eisentraut

1
โปรดทราบว่า MS SQL ไม่ปฏิบัติตามกฎนี้: ค่า NULL หลายค่าจะละเมิดUNIQUEข้อ จำกัด โชคดีที่เริ่มต้นจากปี 2008 คุณสามารถใช้ดัชนีที่กรองแล้วเพื่อรับพฤติกรรมที่เหมาะสม
Jon of All Trades

6

คุณอาจเป็นปัจจัยในการวิจารณ์วันของโมฆะและปัญหาการ 3VL ในSQL และเชิงทฤษฎี (และวิจารณ์ Rubinson ของวันที่วิจารณ์ของลอจิก Nulls สามมูลค่าและความคลุมเครือใน SQL: Critiquing วันที่ของการวิจารณ์ )

ทั้งสองมีการอ้างอิงและพูดคุยกันที่ความยาวในหัวข้อที่เกี่ยวข้องดังนั้นตัวเลือกสำหรับการขจัดคอลัมน์ NULLable จากรุ่น


4

ความคิดใหม่มีอิทธิพลอย่างมากต่อการเลือกNULL/ NOT NULLคือถ้าคุณใช้กรอบงาน ฉันใช้ symfony มากและใช้การอนุญาตให้NULLส่วนต่าง ๆ ของรหัสและการตรวจสอบข้อมูลง่ายขึ้นเมื่อจัดการข้อมูล

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


คำถามเกี่ยวกับ NULL เทียบกับสตริงว่าง (ในคอลัมน์ nullable, IMO) ไม่ใช่ NULL เทียบกับ NOT NULL ใช่ไหม
Gan

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

หรือ @everyone อื่น ๆ เกี่ยวกับความหมายของ NULL กับ NOT NULL คุณสามารถอ้างถึงสิ่งนี้: dba.stackexchange.com/q/63/107
Gan

2

ต้องทำงานกับ Oracle ( ซึ่งไม่อนุญาตให้คุณสร้างความแตกต่าง ) ฉันได้มาถึงข้อสรุปดังต่อไปนี้:

  • จาก POV เชิงตรรกะมันไม่สำคัญ ฉันไม่สามารถนึกถึงตัวอย่างที่น่าสนใจที่ความแตกต่างระหว่าง NULL และ zero-length-string เพิ่มค่าใด ๆ ใน DBMS

  • จากสิ่งต่อไปนี้: คุณมีNULLคอลัมน์ที่สามารถใช้ที่ไม่อนุญาต zero-len ''(โซลูชัน Oracle-ish) หรือNOT NULLคอลัมน์ที่อนุญาต zero-len

  • และจากประสบการณ์ของฉัน''ทำให้รู้สึกมากขึ้นเมื่อประมวลผลข้อมูลตามปกติคุณต้องการประมวลผลการขาดสตริงเป็นสตริงว่างเปล่า: การต่อเรียงข้อมูลการเปรียบเทียบและอื่น ๆ

หมายเหตุ: เพื่อกลับไปใช้ประสบการณ์ Oracle ของฉัน: สมมติว่าคุณต้องการสร้างแบบสอบถามสำหรับคำขอค้นหา หากคุณใช้''คุณสามารถสร้างWHERE columnX = <searchvalue>และมันจะทำงานเพื่อการค้นหาความเท่าเทียมกัน ถ้าคุณใช้ที่คุณต้องทำNULL WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL)Bah! :-)


2

พวกเขายังแตกต่างจากมุมมองการออกแบบ:

เช่น

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

ดูเหมือนกับ:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

ให้แทรกข้อมูลบางอย่าง:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

ตอนนี้ให้ลองด้วย null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

สิ่งนี้ได้รับอนุญาต

Soooooo: nulls ไม่ใช่สตริงที่น่ารำคาญหรือย้อนกลับ

ไชโย


1

หากเราพูดถึงทฤษฎีกฎของ Codd จะบอกว่า RDBMS ต้องปฏิบัติต่อNULLค่านิยมด้วยวิธีพิเศษ

วิธีการใช้นั้นขึ้นอยู่กับสถาปนิกฐานข้อมูลขึ้นอยู่กับโดเมนจริง - งาน - โครงการ - แอพพลิเคชัน - พื้นที่

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