এনভিএল এবং কোলেসেসের মধ্যে ওরাকল পার্থক্য


207

ওরাকলে এনভিএল এবং কোলেসেসের মধ্যে কোনও স্পষ্ট পার্থক্য নেই?

সুস্পষ্ট পার্থক্য হ'ল কোলেসেস তার প্যারামিটার তালিকার প্রথম নাল আইটেমটি ফিরিয়ে দেবে যখন এনভিএল কেবল দুটি পরামিতি নেয় এবং এটি নাল না হলে প্রথমটি ফেরত দেয়, অন্যথায় এটি দ্বিতীয়টি ফিরিয়ে দেয়।

দেখে মনে হচ্ছে এনভিএল কেবল কোলেসেসের একটি 'বেস কেস' সংস্করণ হতে পারে।

আমি কিছু অনুপস্থিত করছি?


উত্তর:


311

COALESCEআরও আধুনিক ফাংশন যা ANSI-92স্ট্যান্ডার্ডের একটি অংশ ।

NVLহয় Oracleএটা চালু হয়, নির্দিষ্ট 80এর আগে কোন মান ছিল।

দুটি মানের ক্ষেত্রে এগুলি প্রতিশব্দ।

তবে এগুলি আলাদাভাবে প্রয়োগ করা হয়।

NVLসর্বদা উভয় যুক্তিই মূল্যায়ন করে, যখন COALESCEযখন এটি প্রথম অ-খুঁজে পায় সাধারণত মূল্যায়ন বন্ধ করে দেয় NULL(কিছু ব্যতিক্রম রয়েছে যেমন ক্রম হিসাবে NEXTVAL):

SELECT  SUM(val)
FROM    (
        SELECT  NVL(1, LENGTH(RAWTOHEX(SYS_GUID()))) AS val
        FROM    dual
        CONNECT BY
                level <= 10000
        )

এটি প্রায় 0.5সেকেন্ডের জন্য চালায় , যেহেতু এটি তৈরি করে না SYS_GUID(), যদিও 1এটি না NULL

SELECT  SUM(val)
FROM    (
        SELECT  COALESCE(1, LENGTH(RAWTOHEX(SYS_GUID()))) AS val
        FROM    dual
        CONNECT BY
                level <= 10000
        )

এটি বোঝে যে 1এটি একটি NULLনয় এবং দ্বিতীয় যুক্তির মূল্যায়ন করে না।

SYS_GUIDএর উত্পন্ন হয় না এবং কোয়েরি তাত্ক্ষণিক।


11
এগুলি ঠিক প্রতিশব্দ নয় ... প্রদত্ত মানগুলি বিভিন্ন ধরণের হলে এনভিএল একটি অন্তর্নিহিত ডেটা টাইপ castালাই তৈরি করে এমন একটি পার্থক্য আপনি খুঁজে পেতে পারেন। সুতরাং উদাহরণস্বরূপ, আমি COALESCE ব্যবহার করে একটি ত্রুটি পেয়ে যাচ্ছিলাম যে এটি দুটি নূন্যমূল্য (একটি স্পষ্টভাবে সেট করা এবং অন্যটি ডাটাবেসের একটি কলাম থেকে নেওয়া হয়েছে টাইপ নং টাইপের), যা কেবল এনভিএলে ফাংশনটি পরিবর্তন করে অদৃশ্য হয়ে যায়।
ড্যানিয়েলমে

170

এনভিএল প্রথম প্যারামিটারের ডেটাটাইপের সাথে অন্তর্নিহিত রূপান্তর করবে, সুতরাং নিম্নলিখিতটি ত্রুটি করে না

select nvl('a',sysdate) from dual;

COALESCE ধারাবাহিক ডেটাটাইপগুলি আশা করে।

select coalesce('a',sysdate) from dual;

একটি 'বেমানান ডেটাটাইপ ত্রুটি' ফেলে দেবে


22

NVL এবং COALESCE কলামটি একটি NUL ফেরত দেয় ক্ষেত্রে ডিফল্ট মান প্রদানের একই কার্যকারিতা অর্জন করতে ব্যবহৃত হয়।

পার্থক্যগুলি হ'ল:

  1. এনভিএল কেবলমাত্র 2 টি আর্গুমেন্ট গ্রহণ করে যেখানে COALESCE একাধিক যুক্তি নিতে পারে
  2. এনভিএল উভয় আর্গুমেন্টকে মূল্যায়ন করে এবং COALESCE একটি নন-নাল মানের প্রথম ঘটতে থামে।
  3. এনভিএল এটি প্রদত্ত প্রথম যুক্তির উপর ভিত্তি করে একটি অন্তর্নিহিত ডেটাটাইপ রূপান্তর করে। COALESCE আশা করে যে সমস্ত আর্গুমেন্ট একই ডেটাটাইপের হবে।
  4. COALESCE প্রশ্নগুলির ক্ষেত্রে ইস্যু দেয় যা ইউনিয়ন ক্লজগুলি ব্যবহার করে। নীচে উদাহরণ
  5. COALESCE হল ANSI স্ট্যান্ডার্ড যেখানে এনভিএল হিসাবে ওরাকল নির্দিষ্ট।

তৃতীয় ক্ষেত্রে উদাহরণ। অন্যান্য ক্ষেত্রে সহজ।

select nvl('abc',10) from dual; এনভিএল হিসাবে কাজ করবে সংখ্যার দশকে স্ট্রিতে রূপান্তর করবে convers

select coalesce('abc',10) from dual; ত্রুটি - অসামঞ্জস্যপূর্ণ ডেটাটাইপগুলি সহ ব্যর্থ হবে: প্রত্যাশিত CHAR নম্বর পেয়েছে

ইউনিয়ন ব্যবহারের ক্ষেত্রে উদাহরণ

SELECT COALESCE(a, sysdate) 
from (select null as a from dual 
      union 
      select null as a from dual
      );

সঙ্গে ব্যর্থ ORA-00932: inconsistent datatypes: expected CHAR got DATE

SELECT NVL(a, sysdate) 
from (select null as a from dual 
      union 
      select null as a from dual
      ) ;

সফল।

আরও তথ্য: http://www.plsqlinformation.com/2016/04/differences-between-nvl-and-coalesce-in-oracle.html


আমি মনে করি না যে "ইউনিয়ন" এর সাথে একটি নির্দিষ্ট সমস্যা রয়েছে এতটাই দেখা যাচ্ছে যে ওরাকল আপনার মধ্যে কাস্ট নাল টাইপ করতে চান ডিফল্টরূপে একটি চরের সাব-ক্যোয়ারী এবং তারপরে আপনার একই আইটেমটি আপনার আইটেম 3 এ তালিকাবদ্ধ রয়েছে (মিশ্র ডেটা) ধরনের)। আপনি যদি এটি TO_DATE (NULL) এ পরিবর্তন করেন তবে আপনি সম্ভবত ত্রুটিটি পাবেন না (আমি যে ওরাকল ব্যবহার করছি তার সংস্করণে আমি ত্রুটিটি পুনরুত্পাদন করতে পারি না)। অন্যথায় আমি আপনার উত্তরটির সাথে একমত এবং প্রশংসা করি। :-)
ছড়িয়ে পড়ে

17

পরিকল্পনা হ্যান্ডলিংয়েও পার্থক্য রয়েছে।

যখন অনুসন্ধানে nvlকোনও ইনডেক্সড কলামের সাথে ফলাফলের তুলনা থাকে তখন ওরাকল শাখা ফিল্টারগুলি সংবিধানের সাথে একটি অনুকূলিত পরিকল্পনা তৈরি করতে সক্ষম হয় ।

create table tt(a, b) as
select level, mod(level,10)
from dual
connect by level<=1e4;

alter table tt add constraint ix_tt_a primary key(a);
create index ix_tt_b on tt(b);

explain plan for
select * from tt
where a=nvl(:1,a)
  and b=:2;

explain plan for
select * from tt
where a=coalesce(:1,a)
  and b=:2;

nvl:

-----------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |         |     2 |    52 |     2   (0)| 00:00:01 |
|   1 |  CONCATENATION                |         |       |       |            |          |
|*  2 |   FILTER                      |         |       |       |            |          |
|*  3 |    TABLE ACCESS BY INDEX ROWID| TT      |     1 |    26 |     1   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | IX_TT_B |     7 |       |     1   (0)| 00:00:01 |
|*  5 |   FILTER                      |         |       |       |            |          |
|*  6 |    TABLE ACCESS BY INDEX ROWID| TT      |     1 |    26 |     1   (0)| 00:00:01 |
|*  7 |     INDEX UNIQUE SCAN         | IX_TT_A |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(:1 IS NULL)
   3 - filter("A" IS NOT NULL)
   4 - access("B"=TO_NUMBER(:2))
   5 - filter(:1 IS NOT NULL)
   6 - filter("B"=TO_NUMBER(:2))
   7 - access("A"=:1)

সমবেত হত্তয়া:

---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |     1 |    26 |     1   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| TT      |     1 |    26 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IX_TT_B |    40 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"=COALESCE(:1,"A"))
   2 - access("B"=TO_NUMBER(:2))

ক্রেডিটগুলি http://www.xt-r.com/2012/03/nvl-coalesce-concatenation.html এ যান ।


6

আর একটি প্রমাণ যা Coalesce () প্রথম অ নাল মান দিয়ে মূল্যায়ন বন্ধ করে না:

SELECT COALESCE(1, my_sequence.nextval) AS answer FROM dual;

এটি চালান, তারপরে চেক করুন my_sequence.currval;


5

আসলে আমি প্রতিটি বিবৃতিতে একমত হতে পারি না।

"COALESCE আশা করে যে সমস্ত আর্গুমেন্ট একই ডেটাটাইপের হবে" "

এটি ভুল, নীচে দেখুন। আর্গুমেন্টগুলি বিভিন্ন ডেটা ধরণের হতে পারে, এটিও নথিভুক্ত করা হয় : যদি এক্সপ্রেসের সমস্ত উপস্থিতি সংখ্যাসূচক ডেটা টাইপ হয় বা কোনও সংখ্যাসূচক ডেটা টাইপ হয় যা স্পষ্টভাবে একটি সংখ্যাসূচক ডেটা টাইপে রূপান্তরিত করা যায় তবে ওরাকল ডাটাবেস সুস্পষ্টভাবে সর্বোচ্চ সংখ্যার অগ্রাধিকার সহ যুক্তিটি নির্ধারণ করে অবশিষ্ট আর্গুমেন্টগুলি সেই তথ্য প্রকারে রূপান্তরিত করে এবং সেই তথ্য প্রকারটি প্রদান করে। । প্রকৃতপক্ষে এটি সাধারণ অভিব্যক্তির বিপরীতেও রয়েছে "COALESCE একটি নন-নাল মানের প্রথম মুহূর্তে থামে", অন্যথায় পরীক্ষার ক্ষেত্রে নং 4 ত্রুটি বাড়াতে হবে না।

পরীক্ষার কেস নং 5 অনুসারে COALESCEতর্কগুলির অন্তর্নিহিত রূপান্তর করে।

DECLARE
    int_val INTEGER := 1;
    string_val VARCHAR2(10) := 'foo';
BEGIN

    BEGIN
    DBMS_OUTPUT.PUT_LINE( '1. NVL(int_val,string_val) -> '|| NVL(int_val,string_val) );
    EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('1. NVL(int_val,string_val) -> '||SQLERRM ); 
    END;

    BEGIN
    DBMS_OUTPUT.PUT_LINE( '2. NVL(string_val, int_val) -> '|| NVL(string_val, int_val) );
    EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('2. NVL(string_val, int_val) -> '||SQLERRM ); 
    END;

    BEGIN
    DBMS_OUTPUT.PUT_LINE( '3. COALESCE(int_val,string_val) -> '|| COALESCE(int_val,string_val) );
    EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('3. COALESCE(int_val,string_val) -> '||SQLERRM ); 
    END;

    BEGIN
    DBMS_OUTPUT.PUT_LINE( '4. COALESCE(string_val, int_val) -> '|| COALESCE(string_val, int_val) );
    EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('4. COALESCE(string_val, int_val) -> '||SQLERRM ); 
    END;

    DBMS_OUTPUT.PUT_LINE( '5. COALESCE(SYSDATE,SYSTIMESTAMP) -> '|| COALESCE(SYSDATE,SYSTIMESTAMP) );

END;
Output:

1. NVL(int_val,string_val) -> ORA-06502: PL/SQL: numeric or value error: character to number conversion error
2. NVL(string_val, int_val) -> foo
3. COALESCE(int_val,string_val) -> 1
4. COALESCE(string_val, int_val) -> ORA-06502: PL/SQL: numeric or value error: character to number conversion error
5. COALESCE(SYSDATE,SYSTIMESTAMP) -> 2016-11-30 09:55:55.000000 +1:0 --> This is a TIMESTAMP value, not a DATE value!

1
পুনরায়: টেস্ট 4 এর বিপরীতে "COALESCE প্রথম অ-নাল মানতে মূল্যায়ন বন্ধ করে" । আমি একমত নই পরীক্ষাগুলি 4 দেখায় যে সংকলক COALESCE এর সাথে ডেটা ধরণের ধারাবাহিকতার জন্য পরীক্ষা করে। প্রথম নন-নাল মান থামানো একটি রানটাইম সমস্যা, সংকলন-সময় সমস্যা নয়। সংকলনের সময় সংকলক জানে না যে তৃতীয় মান (বলুন) নন-নাল হবে; এটি জোর দিয়েছিল যে চতুর্থ যুক্তিটিও সঠিক তথ্য টাইপের হতে পারে, এমনকি যদি চতুর্থ মানটি কখনই মূল্যায়ন হয় না।
ম্যাথগুই

3

যদিও এটি একদম সুস্পষ্ট এবং এমনকি টম এই প্রশ্নটি জিজ্ঞাসা করেছেন এমনভাবে উল্লেখ করেছেন। তবে আবার রাখা যাক।

এনভিএলে কেবল 2 টি যুক্তি থাকতে পারে। কোলেসিসে 2 এরও বেশি থাকতে পারে।

select nvl('','',1) from dual;// ফলাফল:: ORA-00909আর্গুমেন্টের অবৈধ সংখ্যা
select coalesce('','','1') from dual; // আউটপুট: 1 প্রদান করে


3

এনভিএল: মানটি দিয়ে নালটি প্রতিস্থাপন করুন।

CoALESCE: এক্সপ্রেশন তালিকা থেকে প্রথম অ-নাল এক্সপ্রেশনটি ফিরিয়ে দিন।

সারণী: PRICE_LIST

+----------------+-----------+
| Purchase_Price | Min_Price |
+----------------+-----------+
| 10             | null      |
| 20             |           |
| 50             | 30        |
| 100            | 80        |
| null           | null      |
+----------------+-----------+   

নীচে

[1] সমস্ত পণ্যের 10% মুনাফা যুক্ত করে বিক্রয় মূল্য সেট করুন।
[2] যদি কোনও ক্রয়ের তালিকার দাম না থাকে তবে বিক্রয় মূল্য সর্বনিম্ন মূল্য। ছাড়পত্র বিক্রয় জন্য।
[3] এছাড়াও যদি কোনও ন্যূনতম দাম না থাকে, তবে বিক্রয় মূল্য ডিফল্ট দাম "50" হিসাবে সেট করুন।

SELECT
     Purchase_Price,
     Min_Price,
     NVL(Purchase_Price + (Purchase_Price * 0.10), Min_Price)    AS NVL_Sales_Price,
COALESCE(Purchase_Price + (Purchase_Price * 0.10), Min_Price,50) AS Coalesce_Sales_Price
FROM 
Price_List

বাস্তব জীবনের ব্যবহারিক উদাহরণ দিয়ে ব্যাখ্যা করুন।

+----------------+-----------+-----------------+----------------------+
| Purchase_Price | Min_Price | NVL_Sales_Price | Coalesce_Sales_Price |
+----------------+-----------+-----------------+----------------------+
| 10             | null      | 11              |                   11 |
| null           | 20        | 20              |                   20 |
| 50             | 30        | 55              |                   55 |
| 100            | 80        | 110             |                  110 |
| null           | null      | null            |                   50 |
+----------------+-----------+-----------------+----------------------+

আপনি দেখতে পাচ্ছেন যে এনভিএল দিয়ে আমরা বিধিগুলি অর্জন করতে পারি [1], [2]
তবে কোলেসেসির মাধ্যমে আমরা তিনটি নিয়মই অর্জন করতে পারি।


আপনি কি সম্পর্কে বলুন NVL(Purchase_Price + (Purchase_Price * 0.10), nvl(Min_Price,50)) । বা সম্পর্কে: nvl(NVL(Purchase_Price + (Purchase_Price * 0.10), Min_Price) ,50) :)
ফ্লোরিন ঘিটা

কোনটি দ্রুত, কর্মক্ষমতা অনুযায়ী কোনটি ব্যবহার করা উচিত? হাজার রেকর্ড লোড করতে বিবেচনা?
রিকিপ্রগ্রামার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.