Pembenaran LNNVL

12

LNNVL adalah fungsi bawaan oracle yang mengembalikan TRUE untuk kondisi yang mengevaluasi ke FALSE atau UNKNOWN, dan mengembalikan FALSE untuk kondisi yang mengevaluasi ke TRUE. Pertanyaan saya adalah apa untungnya mengembalikan kebalikan dari kondisi kebenaran daripada hanya menangani nilai-nilai NULL?

Misalnya, anggap Anda memiliki tabel Emp dengan kolom StartCommission dan CurrentCommission yang mungkin berisi nol. Berikut ini hanya baris yang tidak memiliki nilai nol:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission;

Jika Anda ingin memasukkan baris di mana salah satu komisi nol, Anda bisa melakukan sesuatu seperti ini:

SELECT * FROM Emp WHERE StartCommission = CurrentCommission 
OR StartCommission IS NULL OR CurrentCommission IS NULL;

Tampaknya ada fungsi untuk mempersingkat sintaks ini, tetapi menggunakan LNNVL mengembalikan semua catatan yang tidak sama dan semua catatan dengan nol.

SELECT * FROM Emp WHERE LNNVL(StartCommission = CurrentCommission);

Menambahkan TIDAK ke ini hanya mengembalikan baris tanpa nol. Tampak bagi saya bahwa fungsi yang diinginkan untuk kasus ini adalah untuk menjaga kondisi true true, kondisi false salah, dan kondisi yang tidak diketahui mengevaluasi ke true. Apakah saya benar-benar membuat kasus penggunaan rendah di sini? Apakah benar-benar lebih mungkin ingin mengubah yang tidak diketahui menjadi benar, benar menjadi salah, dan salah menjadi benar?

create table emp (StartCommission Number(3,2), CurrentCommission Number(3,2));
insert into emp values (null,null);
insert into emp values (null,.1);
insert into emp values (.2,null);
insert into emp values (.3,.4);
Leigh Riffel
sumber
Hari ini saya bertemu dengan LNNVL dan saya berusaha mencari tahu atau memahami bagian ini juga "apa manfaatnya mengembalikan kebalikan dari kebenaran". Namun, pernyataan yang Anda gunakan untuk mencontohkan LNNVL harus menggunakan operator yang tidak sama: SELECT * DARI Emp WHERE LNNVL (StartCommission <> CurrentCommission); sehingga mengembalikan hasil yang sama dengan pernyataan menggunakan OR. Dengan kata lain, jika kami menggunakan suatu kondisi dan kami juga ingin memasukkan baris yang memiliki nilai NULL, kami harus meneruskan negate dari kondisi kami ke LNNVL.
Only You
Contoh sederhana lainnya. Hanya karyawan yang benar-benar menerima komisi kurang dari 20%: PILIH * DARI karyawan WHERE commission_pct <.2; Untuk juga menyertakan karyawan yang tidak menerima komisi sama sekali: PILIH * DARI karyawan DI MANA LNNVL (commission_pct> = .2);
Only You
@OnlyYou - Anda benar, bahwa untuk membuat LNNVL berfungsi sama, kondisinya harus <>. Saya meninggalkannya = lebih karena jika fungsi mengembalikan hasil yang sama dengan tanda = itu akan lebih masuk akal. Pada dasarnya fungsi ini melakukan dua tindakan 1. Null inclusion, 2. Boolean toggle. Yang pertama masuk akal, yang belakangan kelihatannya membingungkan hal-hal yang membutuhkan kebalikan dari kondisi yang diinginkan. yaitu = membutuhkan <>, <membutuhkan> =, dll.
Leigh Riffel

Jawaban:

6

Ini adalah fungsi yang aneh dengan sejarah yang aneh - tapi begitu juga nvl2 aneh. lnnvlpada dasarnya adalah is not trueoperator - tidak diragukan lagi itu dapat digunakan dengan baik seperti nvl2kaleng, tetapi ketika Anda harus melihat fungsi setiap kali Anda menggunakannya untuk mengingatkan Anda apa yang dilakukannya, Anda bertanya-tanya apakah yang terbaik adalah tetap berpegang pada nvl, coalesce, decodedan nullifbersama dengan caseekspresi, yang lebih intuitif

Jack mengatakan coba topanswers.xyz
sumber
Saya tidak menemukan NVL2 aneh, tetapi kemudian saya sering menggunakannya dan saya tidak pernah menggunakan LNNVL.
Leigh Riffel
@ Leeigh - Saya kira Anda harus menggunakannya cukup sering agar tidak aneh :) Saya tidak pernah menggunakannya nullifsampai saya menyadari itu bisa sangat membantu membuat 'pembagian dengan nol' = nol. Apakah Anda benar-benar menemukan nvl2 (a, c, b) jauh lebih baik daripada decode (a, null, b, c)?
Jack bilang coba topanswers.xyz
4

Begini, saya belum pernah menggunakan LNNVL dalam beberapa tahun saya menjadi DBA dan PL / SQL Programmer. Saya telah menggunakan NVL2 pada kesempatan (dan selalu harus mencari sisi mana yang benar, dan sisi mana yang tidak). Pada titik itu, tampaknya lebih baik dari perspektif keterbacaan untuk akhirnya menggunakan NVL, DECODE, KASUS, dll.,

Atau, ini berfungsi, dengan asumsi orang memiliki pegangan yang baik tentang bagaimana Oracle menangani NULL dan aritmatika, tetapi pada titik ini, orang mungkin juga menggunakan permintaan asli Anda untuk keterbacaan (dan rencana pelaksanaan mungkin juga mendapat pukulan lebih keras):

/* Return all rows where StartCommission is the same
 * as Current Commission, or those rows who have a
 * NULL in either (including both)
 */

SELECT *
  FROM Emp
 WHERE StartCommission = CurrentCommission
    OR StartCommission + CurrentCommission IS NULL

-- NULL + NULL, or NULL + Number is always NULL; hence return either
-- those records that are equal, or have a combined total of NULL
-- (either or both fields will be NULL).
Kerri Shotts
sumber
Apakah yang Anda maksud StartCommission<>CurrentCommission OR StartCommission + CurrentCommission IS NULL?
Jack bilang coba topanswers.xyz
@JackPDouglas - Masuk akal sebagai =.
Leigh Riffel
Variasi yang menarik. Saya setuju dengan kesimpulan Anda.
Leigh Riffel
@ Leigh - Begitu ya, alternatif untuk fungsi yang Anda inginkan, bukan alternatif lnnvl.
Jack bilang coba topanswers.xyz
@JackPDouglas - Saya mengerti dan saya pikir itulah yang dimaksudkan Kerri.
Leigh Riffel