Mengapa Oracle 9i memperlakukan string kosong sebagai NULL?


216

Saya tahu itu memang dianggap sebagai NULL, tetapi itu tidak banyak membantu saya untuk mengatakan mengapa ini terjadi. Seperti yang saya pahami spesifikasi SQL, '' tidak sama dengan NULL- satu adalah datum yang valid, dan yang lainnya menunjukkan tidak adanya informasi yang sama.

Jangan ragu untuk berspekulasi, tetapi harap tunjukkan jika itu masalahnya. Jika ada orang dari Oracle yang dapat mengomentarinya, itu akan sangat fantastis!


9
Merasa bebas berspekulasi? Entah bagaimana saya tidak berpikir itu akan memberi Anda set jawaban terbesar ..
SCdF

1
Saya kira tidak, tapi saya tidak yakin akan ada kepastian tentang masalah ini, jadi saya pikir saya akan membuka pintu. Tampaknya sudah berhasil oke, sejauh ini.
Chris R


Jawaban:


216

Saya percaya jawabannya adalah bahwa Oracle sudah sangat, sangat tua.

Kembali di masa lalu sebelum ada standar SQL, Oracle membuat keputusan desain string kosong di VARCHAR/ VARCHAR2kolom NULLdan bahwa hanya ada satu rasa NULL (ada teori relasional yang akan membedakan antara data yang tidak pernah diminta, data di mana jawabannya ada tetapi tidak diketahui oleh pengguna, data di mana tidak ada jawaban, dll. yang semuanya merupakan pengertian NULL).

Pada saat standar SQL muncul dan menyetujui bahwa NULLdan string kosong adalah entitas yang berbeda, sudah ada pengguna Oracle yang memiliki kode yang menganggap keduanya setara. Jadi Oracle pada dasarnya dibiarkan dengan opsi untuk memecahkan kode yang ada, melanggar standar SQL, atau memperkenalkan semacam parameter inisialisasi yang akan mengubah fungsionalitas dari sejumlah besar kueri yang berpotensi. Melanggar standar SQL (IMHO) adalah yang paling tidak mengganggu dari ketiga opsi ini.

Oracle telah membuka kemungkinan bahwa VARCHARtipe data akan berubah dalam rilis mendatang untuk mematuhi standar SQL (itulah sebabnya semua orang menggunakan VARCHAR2Oracle karena perilaku tipe data itu dijamin akan tetap sama di masa mendatang).


60

Tom Kyte VP dari Oracle:

Panjang NOL varchar diperlakukan sebagai NULL.

'' tidak diperlakukan sebagai NULL.

'' ketika ditugaskan ke char (1) menjadi '' (tipe char adalah string padded kosong).

'' ketika ditugaskan ke varchar2 (1) menjadi '' yang merupakan string panjang nol dan string panjang nol adalah NULL di Oracle (tidak lagi '')


17
Wow, Tom agak gila. Mengingat bahwa pertanyaan yang berkaitan dengan divergensi mengerikan dari SQL92, Anda akan berpikir dia akan kurang bersemangat tentang hal itu ... walaupun dia mungkin bosan menjawab.
Chris R

8
Hal terbaik tentang Tom adalah Anda mendapatkan jawaban yang jelas, yang menyatakan dengan tepat apa yang ia pikirkan. Cari beberapa komentar di mana orang telah menggunakan teks berbicara di Ask Tom
Chris Gill

9
Tetapi akan lebih tepat jika baris kedua diubah menjadi '' tidak selalu diperlakukan sebagai NULL.
ypercubeᵀᴹ

2
@ ypercube Kutipan tidak mendapatkan lebih tepat dengan mengubah kata yang sebenarnya digunakan oleh Tom. Jika Anda pikir Tom mengatakannya dengan membingungkan, mmm. Mungkin. Saya pikir dia tepat . Situasi yang paling membingungkan muncul ketika ''sedang implisit dikonversi ke VARCHAR2, seperti cast('' as char(1)) is nullyang ... mengejutkan BENAR
sehe

1
@sehe bit yang membingungkan bagi saya adalah pilih 1 dari dual mana ('' adalah nol)
matt freake

20

Saya menduga ini jauh lebih masuk akal jika Anda memikirkan Oracle seperti yang dilakukan pengembang sebelumnya - sebagai backend yang dimuliakan untuk sistem entri data. Setiap bidang dalam database terkait dengan bidang dalam bentuk yang dilihat oleh operator entri data di layarnya. Jika operator tidak mengetikkan apa pun ke dalam bidang, apakah itu "tanggal lahir" atau "alamat" maka data untuk bidang itu "tidak dikenal". Tidak ada cara bagi operator untuk menunjukkan bahwa alamat seseorang benar-benar string kosong, dan itu tidak masuk akal.


5
Itu hanya masuk akal jika Anda menganggap bahwa setiap bidang dalam sistem entri data adalah wajib. Tidak ada jawaban untuk bidang yang tidak wajib (mis. "Dog's Name") valid, jadi string kosong masih memiliki tujuan yang berbeda dari NULL. Bahkan dengan asumsi itu, saya ragu para pengembang awal menganggap Oracle sebagai "backend yang dimuliakan untuk sistem entri data" jadi saya tidak yakin jawaban ini masuk akal sama sekali.
Jared

19

Dokumentasi Oracle memperingatkan pengembang untuk masalah ini, kembali setidaknya sejauh versi 7.

Oracle memilih untuk mewakili NULLS dengan teknik "nilai yang tidak mungkin". Misalnya, NULL di lokasi numerik akan disimpan sebagai "minus nol", nilai yang tidak mungkin. Setiap nol nol yang dihasilkan dari perhitungan akan dikonversi menjadi positif nol sebelum disimpan.

Oracle juga memilih, secara keliru, untuk mempertimbangkan string VARCHAR dengan panjang nol (string kosong) sebagai nilai yang tidak mungkin, dan pilihan yang cocok untuk mewakili NULL. Ternyata string kosong jauh dari nilai yang tidak mungkin. Ini bahkan identitas di bawah operasi penggabungan string!

Dokumentasi Oracle memperingatkan para perancang dan pengembang basis data bahwa beberapa versi Oracle di masa depan mungkin memutuskan hubungan ini antara string kosong dan NULL, dan memecah kode apa pun yang bergantung pada asosiasi itu.

Ada teknik untuk menandai NULLS selain dari nilai yang tidak mungkin, tetapi Oracle tidak menggunakannya.

(Saya menggunakan kata "lokasi" di atas berarti persimpangan dari suatu baris dan kolom.)


Dokumentasi Oracle memperingatkan perancang dan pengembang basis data bahwa beberapa versi Oracle di masa depan mungkin akan memutuskan hubungan ini antara string kosong dan NULL, dan memecah kode apa pun yang bergantung pada asosiasi itu - dapatkah Anda memberikan referensi untuk pernyataan ini?
Piotr Dobrogost


2

String kosong sama dengan NULL hanya karena itu "kejahatan kurang" jika dibandingkan dengan situasi ketika keduanya (string kosong dan nol) tidak sama.

Dalam bahasa di mana NULL dan String kosong tidak sama, kita harus selalu memeriksa kedua kondisi.


Cukup atur not nullkendala pada kolom Anda dan periksa hanya pada string kosong.
Egor Skriptunoff

6
Memeriksa kedua kondisi itu sepele: WHERE Field <> ''mengembalikan true hanya jika bidang tidak NULL dan tidak kosong, pada database dengan perilaku ANSI untuk string kosong.

1

Menurut dokumen resmi 11g

Oracle Database saat ini memperlakukan nilai karakter dengan panjang nol sebagai nol. Namun, ini mungkin tidak terus menjadi kenyataan di rilis mendatang, dan Oracle merekomendasikan agar Anda tidak memperlakukan string kosong sama dengan nol.

Kemungkinan alasannya

  1. val IS NOT NULL lebih mudah dibaca daripada val != ''
  2. Tidak perlu memeriksa kedua kondisi val != '' and val IS NOT NULL

5
Dalam basis data sepenuhnya ANSI-compliant, Anda tidak perlu memeriksa kedua kondisi. val <> ''sudah dikecualikan NULL. Mungkin maksudmu val = '' OR val IS NULL. Tetapi string kosong yang tidak bisa dibandingkan dengan NULL berguna !
ErikE

Saya setuju dengan bagian perbandingan.
Penyortir

0

Contoh dari buku

   set serveroutput on;   
    DECLARE
    empty_varchar2 VARCHAR2(10) := '';
    empty_char CHAR(10) := '';
    BEGIN
    IF empty_varchar2 IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
    END IF;


    IF '' IS NULL THEN
    DBMS_OUTPUT.PUT_LINE(''''' is NULL');
    END IF;

    IF empty_char IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
    ELSIF empty_char IS NOT NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
    END IF;

    END;

-1

Karena tidak memperlakukannya sebagai NULL juga tidak membantu.

Jika Anda membuat kesalahan dalam bidang ini pada Oracle, Anda biasanya langsung menyadarinya. Namun, dalam SQL server, itu akan berfungsi, dan masalahnya hanya muncul ketika seseorang memasukkan string kosong daripada NULL (mungkin dari pustaka klien .net, di mana null berbeda dari "", tetapi Anda biasanya memperlakukannya sama ).

Saya tidak mengatakan Oracle benar, tetapi menurut saya kedua cara tersebut kira-kira sama buruknya.


2
Jauh lebih mudah untuk di-debug. Juga, jika Anda melihat sel kosong atau input di layar, Anda tahu data dalam DB adalah nol. Di DB lain di mana '' <> NULL, Anda tidak bisa "melihat" apakah datanya nol atau '', ini mengarah ke bug yang sangat licik. '' = null itu pilihan paling jernih, meskipun itu bukan standar.
Lucio M. Tato

2
“Di DB lain di mana '' <> NULL, Anda tidak bisa" melihat "apakah datanya nol atau ''" => Biasanya, alat DB menampilkan NULL berbeda dari string kosong. Sebenarnya, bahkan Oracle SQL Developer menunjukkan NULL sebagai "(null)". Saya kira ini adalah untuk membedakan NULL dari spasi, tetapi tidak terkait dengan perbedaan antara string NULL dan kosong.
Didier L

-6

Memang, saya tidak punya apa-apa selain kesulitan dalam berurusan dengan Oracle, termasuk nilai datetime yang tidak valid (tidak dapat dicetak, dikonversi atau apa pun, hanya melihat dengan fungsi DUMP ()) yang diizinkan untuk dimasukkan ke dalam database, tampaknya melalui beberapa buggy versi klien sebagai kolom biner! Begitu banyak untuk melindungi integritas basis data!

Oracle menangani tautan NULLs:

http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/

http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html


1
nilai data yang tidak valid? Tidak yakin apa artinya itu. Sudahkah Anda memposting ini sebagai pertanyaan di sini?

1
Masalah stackoverflow pra-tanggal - saya tidak mendapat informasi berguna dari forum Oracle dan saya membuat solusi - Saya akan melacak catatan saya dan memposting di sini.
Cade Roux

Detail yang diposting sebagai pertanyaan di sini.
Cade Roux

-6

Pertama-tama, string null dan null tidak selalu diperlakukan sama oleh Oracle. String nol adalah, secara definisi, string yang tidak mengandung karakter. Ini sama sekali tidak sama dengan nol. NULL, menurut definisi, tidak adanya data.

Lima atau enam tahun yang lalu, string nol diperlakukan berbeda dari null oleh Oracle. Sementara, seperti null, null string sama dengan segalanya dan berbeda dari segalanya (yang menurut saya baik-baik saja untuk null, tetapi benar-benar SALAH untuk string nol), setidaknya panjang (string nol) akan mengembalikan 0, sebagaimana seharusnya karena string nol adalah string dengan panjang nol.

Saat ini di Oracle, length (null) mengembalikan null yang saya kira OK, tetapi length (null string) juga mengembalikan null yang benar-benar SALAH.

Saya tidak mengerti mengapa mereka memutuskan untuk mulai memperlakukan 2 nilai "yang berbeda" ini sama. Mereka berarti hal yang berbeda dan programmer harus memiliki kemampuan untuk bertindak pada masing-masing dengan cara yang berbeda. Fakta bahwa mereka telah mengubah metodologi mereka mengatakan kepada saya bahwa mereka benar-benar tidak memiliki petunjuk tentang bagaimana nilai-nilai ini harus diperlakukan.


Kutipan diperlukan untuk membuat perbedaan antara "string nol" dan nilai NULL. Dalam database apa pun kecuali Oracle, VARCHARbidang dapat memiliki nilai (nol atau lebih karakter) atau tidak ada nilai (NULL), berhenti penuh.

"Lima atau enam tahun yang lalu" dari 2011 akan jatuh dalam jangka waktu 10g (10,1 dirilis tahun 2003, 10,2 pada tahun 2005). 10g sama sekali tidak memperkenalkan perubahan global dalam penanganan null, dan tidak pernah ada perbedaan antara NULLdan string bernilai nol, dan perbedaan seperti itu tidak masuk akal. Saya khawatir jawaban ini adalah fantasi lengkap.
William Robertson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.