Oracle 9i가 빈 문자열을 NULL로 취급하는 이유는 무엇입니까?


216

나는 그것이 알고 않는 으로 '고려 NULL하지만 나에게 많은 일을하지 않는 이유는 이 경우이다. SQL 사양을 이해함에 따라 ''는 같지 않습니다. NULL하나는 유효한 데이텀이고 다른 하나는 동일한 정보가 없음을 나타냅니다.

자유롭게 추측하되, 그 경우에 표시하십시오. 오라클의 누군가가 그것에 대해 의견을 말할 수 있다면 환상적입니다!


9
자유롭게 추측 하시겠습니까? 어쨌든 나는 그것이 당신에게 가장 큰 대답을 줄 것이라고 생각하지 않습니다 ..
SCdF

1
나는 그렇지 않다고 생각하지만, 그 주제에 대해 확실하지 않다고 확신했기 때문에 문을 열어 놓을 것이라고 생각했다. 지금까지 문제가 해결 된 것 같습니다.
Chris R


답변:


216

답은 오라클이 매우 오래되었다는 것입니다.

예전에는 SQL 표준이 존재하기 전인 오라클은 빈 열의 문자열 VARCHAR/ VARCHAR2열이 NULLNULL이고 단 하나의 NULL 만 있다는 설계 결정을 내 렸습니다 . 답변이 존재하지만 사용자에 의해 알려지지 않은 데이터, 답변이없는 데이터 등은 모두 어떤 의미를 갖습니다 NULL).

SQL 표준이 등장 NULL하고 빈 문자열이 별개의 엔터티라는 데 동의했을 때 이미 두 사용자가 동등한 것으로 가정 한 코드를 가진 Oracle 사용자가있었습니다. 따라서 Oracle은 기본적으로 기존 코드를 깨거나 SQL 표준을 위반하거나 잠재적으로 많은 수의 쿼리 기능을 변경하는 일종의 초기화 매개 변수를 도입하는 옵션이 남아있었습니다. SQL 표준 (IMHO)을 위반하는 것이이 세 가지 옵션 중에서 가장 파괴적이었습니다.

오라클은 VARCHAR향후 릴리스에서 SQL 표준을 준수하기 위해 데이터 유형이 변경 될 가능성을 열어 놓았습니다 (그래서 VARCHAR2해당 데이터 유형의 동작이 계속 동일하게 유지되기 때문에 모든 사람 이 Oracle에서 사용하는 이유 ).


60

Tom Kyte 오라클 부사장 :

ZERO 길이 varchar는 NULL로 처리됩니다.

''는 NULL로 취급되지 않습니다.

''는 char (1)에 할당 될 때 ''가됩니다 (문자 유형은 공백으로 채워진 문자열입니다).

''varchar2 (1)에 할당되면 ''는 길이가 0 인 문자열이고 길이가 0 인 문자열은 Oracle에서 NULL입니다 (더 이상은 아닙니다)


17
와우, 톰은 꽤 비꼬다. 질문이 SQL92의 엄청난 발산과 관련이 있다는 것을 감안할 때, 당신은 그가 답답하지는 않지만 그에 대해 덜 펀치 적이라고 생각할 것입니다.
Chris R

8
Tom의 가장 좋은 점은 자신이 생각 하는 것을 정확하게 나타내는 명확한 대답을 얻는 것입니다. 사람들이 Ask Tom
Chris Gill에서

9
그러나 두 번째 줄이 ''
ypercubeᵀᴹ

2
@ypercube Tom이 실제로 사용하는 단어를 변경하면 견적이 더 정확 해지지 않습니다. 톰이 혼란스럽게 생각한다고 생각한다면, mmm. 아마도. 나는 그가 자리에 있다고 생각 합니다 . 때 가장 혼란 상황이 발생 ''되고 묵시적으로 VARCHAR2로 변환 같은 cast('' as char(1)) is null인 ... 놀라 울 TRUE
sehe

1
@sehe 나를 위해 혼란스러운 비트는 듀얼에서 1을 선택합니다. ( ''는 null)
matt freake

20

필자는 초기 개발자가했던 방식대로 Oracle을 데이터 입력 시스템의 영광스러운 백엔드로 생각하면 이것이 더 의미가 있다고 생각합니다. 데이터베이스의 모든 필드는 데이터 입력 운영자가 화면에서 본 양식의 필드에 해당합니다. 운영자가 "생년월일"또는 "주소"에 관계없이 필드에 아무것도 입력하지 않은 경우 해당 필드의 데이터는 "알 수 없음"입니다. 운영자가 누군가의 주소가 실제로 빈 문자열임을 나타낼 방법이 없으며, 어쨌든 그다지 의미가 없습니다.


5
데이터 입력 시스템의 모든 필드가 필수라고 가정하는 경우에만 의미가 있습니다. 필수가 아닌 필드 (예 : "Dog 's Name")에 대한 비답은 유효하므로 빈 문자열은 여전히 ​​NULL과 다른 용도로 사용됩니다. 그 가정이 있었음에도 불구하고 초기 개발자가 Oracle을 "데이터 입력 시스템의 영광스러운 백엔드"로 생각한 것이 의심 스럽기 때문에이 답변이 전혀 의미가 있는지 확신 할 수 없습니다.
Jared

19

Oracle 설명서는 개발자에게이 문제에 대해 경고하며 최소한 버전 7까지 거슬러 올라갑니다.

오라클은 "불가능한 값"기술로 NULLS를 나타내기로 결정했습니다. 예를 들어, 숫자 위치의 NULL은 불가능한 값인 "마이너스 0"으로 저장됩니다. 계산 결과 마이너스 0은 저장되기 전에 양의 0으로 변환됩니다.

또한 Oracle은 길이가 0 인 VARCHAR 문자열 (빈 문자열)을 불가능한 값으로 간주하고 NULL을 표시하기에 적합한 선택으로 잘못 선택했습니다. 빈 문자열은 불가능한 값과 거리가 멀다는 것이 밝혀졌습니다. 문자열 연결 작업의 정체성이기도합니다!

Oracle 설명서는 데이터베이스 설계자와 개발자에게 향후 버전의 Oracle이 빈 문자열과 NULL 사이에서이 연관을 해제하고 해당 연관에 종속 된 코드를 손상시킬 수 있다고 경고합니다.

불가능한 값 이외의 NULLS 플래그를 지정하는 기술이 있지만 Oracle은이를 사용하지 않았습니다.

(위의 "location"이라는 단어를 사용하여 행과 열의 교차점을 의미합니다.)


오라클 문서는 데이터베이스 디자이너와 개발자에게 향후 버전의 오라클이 빈 문자열과 NULL 사이에서이 연결을 끊을 수 있으며 그 연결에 의존하는 코드를 손상시킬 수 있다고 경고합니다. 이 문장에 대한 참조를 제공해 주시겠습니까?
Piotr Dobrogost


2

빈 문자열은 두 문자열 (빈 문자열과 null)이 동일하지 않은 상황과 비교할 때 "더 적은 악"으로 인해 단순히 NULL과 동일합니다.

NULL과 빈 문자열이 같은 언어에서는 항상 두 조건을 모두 확인해야합니다.


not null열에 제약 조건을 설정 하고 빈 문자열에서만 확인하십시오.
Egor Skriptunoff 2016 년

6
두 조건을 선택하면 간단하다 : WHERE Field <> ''true를 반환 필드가 빈 문자열에 대한 ANSI 행동으로 데이터베이스에 NULL하지 않고 버리지 만.

1

공식 11g 문서에 따르면

Oracle Database는 현재 길이가 0 인 문자 값을 널로 처리합니다. 그러나 이것은 향후 릴리스에서 계속 적용되지 않을 수 있으므로 빈 문자열을 null과 동일하게 처리하지 않는 것이 좋습니다.

가능한 이유

  1. val IS NOT NULL 보다 읽기 쉽다 val != ''
  2. 두 조건을 모두 확인할 필요가 없습니다 val != '' and val IS NOT NULL

5
완전한 ANSI 호환 데이터베이스에서는 두 가지 조건을 모두 확인할 필요가 없습니다. val <> ''이미 제외되었습니다 NULL. 아마도 당신은 의미했다 val = '' OR val IS NULL. 그러나 NULL로 비교하지 않는 빈 문자열이 유용합니다 !
ErikE

나는 비교 부분에 동의합니다.
Sorter

0

책의 예

   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

NULL로 처리하지 않는 것도 특히 도움이되지 않습니다.

Oracle의이 영역에서 실수를하면 일반적으로 즉시 알 수 있습니다. 그러나 SQL Server에서는 작동하는 것으로 보이며 누군가가 NULL 대신 빈 문자열을 입력 할 때만 문제가 나타납니다 (아마도 ""과 다른 .net 클라이언트 라이브러리에서 발생하지만 일반적으로 동일하게 취급 함) ).

나는 오라클이 옳다고 말하지는 않지만 두 가지 방법이 거의 똑같이 나쁘다.


2
훨씬 더 쉽게 디버깅 할 수 있습니다. 또한 화면에 빈 셀이나 입력이 있으면 DB의 데이터가 null임을 알 수 있습니다. ''<> NULL 인 다른 DB에서는 데이터가 null이거나 ''인 경우 "볼"수 없으므로 매우 부적절한 버그가 발생합니다. ''= null이 표준이 아니더라도 가장 안전한 옵션입니다.
Lucio M. Tato

2
“ ''<> NULL 인 다른 DB에서는 데이터가 null이거나 ''인 경우 "볼 수 없습니다" ''=> 일반적으로 DB 도구는 빈 문자열과 다르게 NULL을 표시합니다. 실제로 Oracle SQL Developer조차도 NULL을“(null)”로 표시합니다. 나는 이것이 공백과 NULL을 구별하는 것이라고 생각하지만 NULL과 빈 문자열의 차이점과는 관련이 없습니다.
Didier L

-6

사실, 내가 잘못된 날짜 값을 포함, 오라클 다루는 것도 있지만 어려움이 없었습니다되는 (단지 DUMP () 함수를 보았다, 변환 또는 아무것도, 인쇄 할 수 없습니다) 허용 분명히 몇 가지 버그를 통해 데이터베이스에 삽입 이진 열로 클라이언트 버전! 데이터베이스 무결성을 보호하기 위해 너무 많은!

NULL 링크의 Oracle 처리 :

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

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


1
유효하지 않은 데이터 시간 값? 그게 무슨 뜻인지 잘 모르겠습니다. 여기에 질문으로 게시 했습니까?

1
문제가 오래된 스택 오버 플로우-Oracle 포럼에서 유용한 정보를 얻지 못했고 해결 방법을 만들었습니다. 노트를 추적하고 여기에 게시 할 것입니다.
Cade Roux

질문으로 여기에 세부 정보를 게시했습니다.
Cade Roux

-6

우선, 널 (null)과 널 (null) 문자열은 항상 Oracle에서 동일하게 취급되지 않았습니다. 널 문자열은 정의상 문자가없는 문자열입니다. 이것은 null과 전혀 다릅니다. NULL은 정의상 데이터가 없음입니다.

5 년 또는 6 년 전, null 문자열은 Oracle에 의해 null과 다르게 취급되었습니다. null과 같이 null 문자열은 모든 것과 같고 모든 것과 다릅니다 (null에는 괜찮지 만 null 문자열에는 완전히 WRONG이라고 생각합니다) .null 문자열이 있기 때문에 적어도 length (null 문자열)는 0을 반환합니다. 길이가 0 인 문자열

현재 Oracle에서 length (null)은 null을 반환하지만 괜찮습니다. length (null string)도 완전히 잘못 된 null을 반환합니다.

그들이 왜이 두 가지 "값"을 동일하게 취급하기로 결정했는지 이해가되지 않습니다. 그것들은 다른 것을 의미하며 프로그래머는 서로 다른 방식으로 행동 할 수 있어야합니다. 그들이 방법론을 변경했다는 사실은 그들이 어떻게 이러한 가치를 다루어야하는지에 대한 실마리가 없다는 것을 말해줍니다.


"널 문자열"과 NULL 값을 구별하기 위해 인용이 필요합니다. Oracle을 제외한 모든 데이터베이스에서 VARCHAR필드는 값 (0 개 이상의 문자)을 갖거나 값이없는 (NULL), 완전 정지를 가질 수 있습니다.

2011 년부터 "5-6 년 전"은 10g 기간 (2003 년 10.1 릴리스, 2005 년 10.2)에 해당합니다. 10g는 널 처리에있어 전역적인 변화를 전혀 나타내지 않았 NULL으며, 널값 문자열과의 구별은 없었으며, 그러한 구별은 의미가 없습니다. 이 답변이 완전한 환상이라는 것이 두렵습니다.
윌리엄 로버트슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.