programing

경험이 풍부한 새로운 고객을 위한 Oracle Gotchas

javajsp 2023. 8. 12. 09:48

경험이 풍부한 새로운 고객을 위한 Oracle Gotchas

일반적으로 관계형 데이터베이스(MySQL, MS SQL Server, Postgres 등)는 아니지만 플랫폼에는 새로 온 사용자를 위한 Oracle gotchas는 무엇입니까?

제가 찾고 있는 것의 두 가지 예는

  1. 많은 관계형 데이터베이스 제품은 사용자를 위해 auto_increment 키 생성을 처리합니다.Oracle이 그렇지 않습니다. 시퀀스를 수동으로 생성한 다음 트리거를 생성해야 합니다.

  2. SQL Developer 인터페이스를 통해 데이터를 삽입할 때는 데이터를 수동으로 커밋해야 합니다.

PHP 관련 gotchas에 대한 보너스 포인트, 그것이 플랫폼이기 때문에 이 가상의 경험이 풍부한 newb가 사용할 것입니다.

참고: 여기서는 gotchas만 설명하고 있습니다. 즉, 다음과 같은 상황입니다.Oracle다른 시스템처럼 작동하지 않습니다.Oracle다른 것들보다 많은 이점을 가지고 있습니다.RDBMS의 주제가 , 하만그주아제닙다니가게의시물.

  • 은 다니없습.SELECT 없이FROM.

    SELECT  1
    

    실패할 경우 다음 작업을 수행해야 합니다.

    SELECT  1
    FROM    dual
    
  • 과 " " " "NULL같은 것입니다.

    SELECT  *
    FROM    dual
    WHERE   '' = ''
    

    아무것도 반환하지 않습니다.

  • 다 없어요.TOP도 아니다LIMIT에서 합니다.WHERE절:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    정확히 이런 식으로, 서브쿼리를 사용한 이후로.ROWNUM가 앞에 ORDER BY.

  • 상관된 하위 쿼리를 한 수준 이상 깊이 중첩할 수 없습니다.이 작업은 실패합니다.

    SELECT  (
            SELECT  *
            FROM    (
                    SELECT  dummy
                    FROM    dual di
                    WHERE   di.dummy = do.dummy
                    ORDER BY
                            dummy
                    )
            WHERE   rownum = 1
            )
    FROM    dual do
    

    이것이 문제가 된다.

  • NULL값이 인덱싱되지 않았습니다.과 같은 하여 주문하지 않습니다.

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    ,~하지 않는 한col는 로표됩니다로 되어 있습니다.NOT NULL.

    주목할 만한 것은NULL 열이 아니라 인덱스되지 않은 입니다.null 가능한 열에 인덱스를 생성할 수 있습니다.NULL값이 인덱스에 들어갑니다.

    에서 " 나쿼리조다음과같이가때사않인다습용니지되는덱스그정할러건이▁that▁will다▁index"로 가정할 때는 인덱스가 NULL가치는 아마도 그것을 만족시킬 수 있습니다.

    (" " " " " " " ( " " " " " " 포함).NULL. 못합니다 그렇다면 인덱스는 non-에 대해 알지 못합니다.NULL따라서 값을 검색할 수 없습니다.

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    그러나 이 쿼리는 다음 인덱스를 사용합니다.

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            WHERE   col IS NOT NULL
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    가 아닌 때부터NULL값은 조건을 충족할 수 없습니다.

  • 기적으로본,NULL는 첫 번째가 마지막으로 됩니다( 정 다니렬됩로으막는지아마첫닌째번가예▁in▁s(:▁s다니정됩렬like▁are▁last는▁sorted,로:PostgreSQL그러나 과는 달리MySQL그리고.SQL Server)

    다음 쿼리:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id
    

    돌아올 것입니다

    id
    ---
    1
    NULL
    

    정하기와 같이 SQL Server그리고.MySQL사용:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id NULLS FIRST
    

    깨짐에 유의rownum하위 쿼리에서 후자를 사용하지 않는 경우(위에서 설명한 것과 동일),

  • "MYTABLE"그리고."mytable"(큰따옴표가 중요함)는 서로 다른 개체입니다.

    SELECT  *
    FROM    mytable -- wihout quotes
    

    후자가 아닌 전자 중에서 선택할 것입니다.전자가 없으면 쿼리가 실패합니다.

    CREATE TABLE mytable
    

    "MYTABLE",것은 아니다."mytable".

  • Oracle모든 암묵적 잠금(이로 인해 발생합니다.DML운영)은 행 레벨이며 결코 에스컬레이션되지 않습니다.트랜잭션의 영향을 받지 않는 행은 암시적으로 잠글 수 없습니다.

    작가들은 결코 독자들을 차단하지 않습니다.

    으로 .LOCK TABLE진술.

    행 잠금은 데이터 페이지에 저장됩니다.

  • Oracle"없니다습"는 CLUSTERED인덱스", "인덱스로 구성된 테이블"이 있습니다..SQL Server그리고.MySQL와 함께InnoDB).

    Oracle월드, "데이터베이스 스토리지"란 여러 테이블에서 공통 키를 공유하는 행이 데이터 페이지를 공유하도록 여러 테이블을 구성하는 것을 의미합니다.

    단일 데이터 페이지는 여러 테이블의 여러 행을 호스트하므로 이 키에 대한 조인 속도가 매우 빠릅니다.

1번을 선택하면 작동하지 않습니다. 대신 듀얼에서 1번을 선택하십시오.

계층형 데이터로 작업하는 경우 연결 기준이 좋습니다.

하나의 댓글:Sybase/SQL Server IDENTITY 열의 동작을 복제하는 것에 대해 확신하지 않는 한 시퀀스를 사용하기 위해 트리거를 생성할 필요가 없습니다.저는 시퀀스를 실제 삽입문에 직접 사용하는 것이 더 유용하다고 생각합니다.

INSERT
  INTO MyTable
     ( KeyCol
     , Name
     , Value
     )
SELECT Seq_MyTable.NextVal
     , 'some name'
     , 123
  FROM dual;

트리거 실행의 오버헤드에 대해 걱정할 필요가 없으며, 스키마에서 다른 스키마로 데이터를 이동할 때와 같이 시퀀스 값이 할당될 필요 없이 테이블에 행을 삽입하는 작업을 유연하게 처리할 수 있습니다.IDENTITY 기능이 어렵거나 불가능하게 만드는 데이터 및 기타 기술 범위를 삽입하기 위해 시퀀스에서 값을 미리 선택할 수도 있습니다.

행 집합에서 null 값으로 완전히 채워질 수 있는 열 주위에 nvl(열)을 사용하는 것을 잊지 마십시오.그렇지 않으면 행 집합에서 열이 누락됩니다.

맞아요, 완전히 놓쳤어요!

예:

SELECT nvl(employeeName,'Archie'), nvl(employeeSpouse,'Edith') FROM Employee

이렇게 하면 행 집합의 모든 값이 null인 경우에도 행 집합에 두 개의 열이 표시됩니다.여러분은 그저 '아키'와 '에디스'의 가치들을 많이 보게 될 것입니다.nvl()을 사용하지 않으면 열을 하나만 얻거나 둘 다 되돌릴 수 없습니다.개발 환경에서 코드가 잘 실행되고 QA를 통과할 수도 있지만, 프로덕션 단계에서 테이블의 결과의 구조를 바꿀 수도 있습니다.

즉, null 가능한 열을 선택할 때마다 nvl()을 사용해야 합니다.

SQL Server보다 스키마 개체와 데이터에 대소문자를 구분하는 Oracle 데이터베이스가 더 많습니다.

여기에 몇 가지 차이점을 적어 두었습니다.ANSI 표준 SQL이 데이터베이스 간에 완벽하게 이동할 수 있다고 생각하십니까? 다시 생각해 보세요.

임시 테이블

일반 테이블처럼 만들고 인덱싱하지만 모든 세션/트랜잭션은 자체 데이터만 봅니다.이것은 MS SQL과 다릅니다.

전역 변수

참조를 통해 전달됩니다.즉, 전역 변수를 모수로 프로시저에 전달하고 프로시저 내부의 전역 변수를 수정하면 모수 값도 변경됩니다.하지만 그다지 인기 있는 방법은 아닙니다.

트리거

매우 최근 버전까지 유사한 트리거가 발생할 방법을 결정할 수 있는 방법은 없었습니다.어떤 "각 행에 대한 업데이트 전"이 처음인지에 대해 정말로 관심이 있다면 모든 것을 하나의 트리거에 넣습니다.

MySQL과 같은 그룹 연결이 없습니다.만약 당신이 그룹 연결 집계 함수를 원한다면, 당신은 당신 자신의 것을 작성해야 합니다.다음은 제 구현입니다.

drop type T_GROUP_CONCAT;

create or replace type GROUP_CONCAT_PARAM as object
(
  val varchar2(255),
  separator varchar2(10),
  numToConcat NUMBER,
  MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt  return VARCHAR2
);

--map function needed for disctinct in select clauses
CREATE OR REPLACE TYPE BODY GROUP_CONCAT_PARAM IS
    MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt return VARCHAR2 is 
      begin 
        return val; 
      end; 

end;


/

CREATE OR REPLACE TYPE T_GROUP_CONCAT 
AS OBJECT (

runningConcat VARCHAR2(5000),
runningCount NUMBER,

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN       GROUP_CONCAT_PARAM
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate
  ( self             IN   T_GROUP_CONCAT,
    returnValue  OUT VARCHAR2,
    flags           IN   NUMBER
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge
  (self  IN OUT T_GROUP_CONCAT,
   ctx2 IN      T_GROUP_CONCAT
  ) RETURN NUMBER

);
/

CREATE OR REPLACE TYPE BODY T_GROUP_CONCAT AS

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER IS 
  BEGIN
    IF actx IS NULL THEN
      actx := T_GROUP_CONCAT ('', 0);
    ELSE
      actx.runningConcat := '';
      actx.runningCount := 0;
    END IF;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN     GROUP_CONCAT_PARAM
  ) RETURN NUMBER IS
  BEGIN
    if self.runningCount = 0 then
        self.runningConcat := val.val;
    elsif self.runningCount < val.numToConcat then
        self.runningConcat := self.runningConcat || val.separator || val.val;
    end if;
    self.runningCount := self.runningCount + 1;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateTerminate
  ( self        IN  T_GROUP_CONCAT,
    ReturnValue OUT VARCHAR2,
    flags       IN  NUMBER
  ) RETURN NUMBER IS
  BEGIN
    returnValue := self.runningConcat;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateMerge
  (self IN OUT T_GROUP_CONCAT,
   ctx2 IN     T_GROUP_CONCAT
  ) RETURN NUMBER IS
  BEGIN
    self.runningConcat := self.runningConcat || ',' || ctx2.runningConcat;
    self.runningCount := self.runningCount + ctx2.runningCount;
    RETURN ODCIConst.Success;
  END;

END;
/

CREATE OR REPLACE FUNCTION GROUP_CONCAT
( x GROUP_CONCAT_PARAM
) RETURN VARCHAR2
--PARALLEL_ENABLE
AGGREGATE USING T_GROUP_CONCAT;
/

사용 방법:

select GROUP_CONCAT(GROUP_CONCAT_PARAM(tbl.someColumn, '|', 2)) from someTable tbl

언급URL : https://stackoverflow.com/questions/1209039/oracle-gotchas-for-an-experienced-newb