简体   繁体   English

在Oracle中使用null运算符而不使用outs检查null的替代方法是什么

[英]what is the alternative way to check for null with out using is null operator in oracle

I had written an stored procedure where selecting from one table(some columns have null data) and inserting into other table with out duplicates. 我编写了一个存储过程,其中从一个表中进行选择(某些列的数据为空),然后插入没有重复的另一个表中。

part of my stored procedure code: 我的存储过程代码的一部分:

 LOOP
   BEGIN
     SELECT ID
       INTO ROWCOUNT
   FROM TBL_EMPLOYEE
 WHERE 

     NAME      = TEMPTABLE.NAME
  AND AGE           =TEMPTABLE.AGE

EXCEPTION
WHEN no_data_found THEN
  ROWCOUNT := 0;
END;
IF ROWCOUNT = 0 THEN
  INSERT INTO TARGET TABLE ......

In the above piece of code there is null data for some columns(eg: TEMPTABLE.AGE etc). 在上面的代码中,某些列(例如TEMPTABLE.AGE等)没有空数据。 when there is null value it is throwing no_data_found exception and it is inserting the data. 当值为null时,它将引发no_data_found异常,并正在插入数据。 we tried alternatively by putting nvl function which is taking more time. 我们通过放置nvl函数来尝试,这花费了更多时间。

LOOP
BEGIN
  SELECT ID
  INTO ROWCOUNT
  FROM TBL_EMPLOYEE
 WHERE 

     nvl(NAME,0000)      = nvl(TEMPTABLE.NAME,0000)
  AND nvl(AGE,0000)           =nvl(TEMPTABLE.AGE,0000)

EXCEPTION
WHEN no_data_found THEN
  ROWCOUNT := 0;
END;
IF ROWCOUNT = 0 THEN
  INSERT INTO TARGET TABLE ......

Can any one suggest any alternative how to do null check with equals to operator. 谁能建议任何替代方法如何用等于运算符进行空值检查。 I have tried it with LIKE as well but it did not work. 我也尝试过LIKE,但是没有用。

You are going about the check in the wrong way. 您正在以错误的方式进行检查。 Eliminate both the ROWCOUNT variable and the loop altogether and use NOT EXISTS() : 完全消除ROWCOUNT变量和循环,并使用NOT EXISTS()

BEGIN
  INSERT INTO TARGET_TABLE
  SELECT .....
  FROM DUAL 
  WHERE NOT EXISTS (
    SELECT *
    FROM TBL_EMPLOYEE
    WHERE nvl(NAME,0000) = nvl(TEMPTABLE.NAME,0000)
    AND nvl(AGE,0000) = nvl(TEMPTABLE.AGE,0000);
END

And your condition may have a bug: If your intention is to treat two nulls as "equal", change the condition to: 而且您的条件可能有一个错误:如果您打算将两个null视为“相等”,请将条件更改为:

WHERE (NAME = TEMPTABLE.NAME OR NVL(NAME, TEMPTABLE.NAME) IS NULL)
AND (AGE = TEMPTABLE.AGE OR NVL(AGE, TEMPTABLE.AGE) IS NULL)

Replace 更换

nvl(NAME,0000) = nvl(TEMPTABLE.NAME,0000)

with

(NAME is NULL and TEMPTABLE.NAME is null or NAME = TEMPTABLE.NAME)

I think you want to do this: 我认为您想这样做:

NAME = VALUE {in case of Some Value}

and

NAME IS NULL {in case the value is null}

ORACLE doesn't handles it by its own. ORACLE不会自行处理。 I think this is a logical condition and this should be handled logically. 我认为这是一个逻辑条件,应该对此进行逻辑处理。 Let me know if I have answered/understood you correctly? 让我知道我是否正确回答/理解了您?

Try to explain in the simplest terms what you want to accomplish. 尝试用最简单的术语解释您要完成的工作。 You give a confusing set of requirements, and are throwing in some code that puts us probably on the wrong track anyhow. 您提出了一系列令人困惑的要求,并且抛出了一些代码,无论如何它们可能使我们走上了错误的道路。 Likely what you need can be done in one statement, without a loop. 您可能需要的内容可以在一条语句中完成,而无需循环。 Some Attempts: 一些尝试:

Remove duplicates by some key columns [name,age] distinguished by the value of another. 删除某些键列[name,age]中的重复项,并用另一个键的值来区分。

INSERT INTO target (name,age,other_value1,other_value2)
SELECT
  name, age,other_value1,other_value2
FROM (
  SELECT
    name,
    age,
    other_value1,
    other_value2,
    ROW_NUMBER() OVER (PARTITION BY name,age ORDER BY other_value1) rn
  FROM source
  ) WHERE rn = 1

The distinguishing column, could be a timestamp of when the data was entered, for which you could use something like ROW_NUMBER() OVER (PARTITION BY name,age ORDER BY time_entered DESC) rn to keep the most recent record. 区别列可以是输入数据的时间戳,为此您可以使用ROW_NUMBER() OVER (PARTITION BY name,age ORDER BY time_entered DESC) rn保存最新记录。

Remove duplicates based on all columns 根据所有列删除重复项

INSERT INTO target (name,age,other_value1,other_value2)
SELECT
  name, age,other_value1,other_value2
FROM source
GROUP BY name,age,other_value1,other_value2
BEGIN
  SELECT ID
  INTO ROWCOUNT
  FROM TBL_EMPLOYEE
 WHERE decode(NAME,TEMPTABLE.NAME,1)=1
   AND decode(AGE,TEMPTABLE.AGE,1)=1
EXCEPTION
WHEN no_data_found THEN
  ROWCOUNT := 0;
END;

And it works with any simple datatype - number varchar2, date and etc. 它适用于任何简单的数据类型-数字varchar2,日期等。

My solution is: 我的解决方案是:

SELECT Name, Age FROM TBL_EMPLOYEE WHERE NAME = 'yourName' AND ( (AGE = yourAge) OR (AGE IS NULL AND yourAge is NULL) ) 选择名称,年龄从TBL_EMPLOYEE,其中NAME ='yourName'AND((AGE = yourAge)OR(AGE为NULL并且yourAge为NULL))

Here NAME and AGE are table column names. NAME和AGE是表列名称。 'yourName' and 'yourAge' are runtime values passed. “ yourName”和“ yourAge”是传递的运行时值。

Let me know if it don't work for you. 让我知道它是否不适合您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM