SQL Server의 Oracle RowID와 동일


82

SQL Server에서 Oracle의 RowID에 해당하는 것은 무엇입니까?


Stephanie : 데이터에 고유 한 키가 있다는 가정은 데이터가 정규화되었다고 가정합니다. 이는 때때로 잘못된 가정입니다. 따라서 SQL 서버에서 Oracle의 RowID와 동일한 것은 무엇입니까?
Christopher Mahan

답변:


115

Oracle 문서에서

ROWID 의사 열

데이터베이스의 각 행에 대해 ROWID 의사 열은 행의 주소를 반환합니다. Oracle Database rowid 값에는 행을 찾는 데 필요한 정보가 포함되어 있습니다.

  • 개체의 데이터 개체 번호
  • 행이있는 데이터 파일의 데이터 블록
  • 데이터 블록에서 행의 위치 (첫 번째 행은 0)
  • 행이있는 데이터 파일입니다 (첫 번째 파일은 1 임). 파일 번호는 테이블 스페이스에 상대적입니다.

SQL Server에서 이것에 가장 가까운 것은 rid세 가지 구성 요소가있는 것 File:Page:Slot입니다.

SQL Server 2008에서는 문서화되지 않고 지원되지 않는 %%physloc%%가상 열을 사용하여 이를 확인할 수 있습니다. 이렇게 binary(8)하면 처음 4 바이트의 페이지 ID, 파일 ID의 경우 2 바이트, 페이지의 슬롯 위치에 대한 2 바이트 의 값 이 반환 됩니다.

스칼라 함수 sys.fn_PhysLocFormatter또는 sys.fn_PhysLocCrackerTVF를 사용하여이를 더 읽기 쉬운 형식으로 변환 할 수 있습니다.

CREATE TABLE T(X INT);

INSERT INTO T VALUES(1),(2)

SELECT %%physloc%% AS [%%physloc%%],
       sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot]
FROM T

예제 출력

+--------------------+----------------+
|    %%physloc%%     | File:Page:Slot |
+--------------------+----------------+
| 0x2926020001000000 | (1:140841:0)   |
| 0x2926020001000100 | (1:140841:1)   |
+--------------------+----------------+

이것은 쿼리 프로세서에서 활용되지 않습니다. 절 에서 이것을 사용 하는 것이 가능 하지만WHERE

SELECT *
FROM T
WHERE %%physloc%% = 0x2926020001000100 

SQL Server는 지정된 행을 직접 찾지 않습니다 . 대신 전체 테이블 스캔을 수행하고 %%physloc%%각 행을 평가 하고 일치하는 행을 반환합니다 (있는 경우).

앞서 언급 한 2 개의 함수에 의해 수행 된 프로세스를 반대로하고 binary(8)알려진 File, Page, Slot 값에 해당 하는 값을 얻으려면 아래를 사용할 수 있습니다.

DECLARE @FileId int = 1,
        @PageId int = 338,
        @Slot   int = 3

SELECT CAST(REVERSE(CAST(@PageId AS BINARY(4))) AS BINARY(4)) +
       CAST(REVERSE(CAST(@FileId AS BINARY(2))) AS BINARY(2)) +
       CAST(REVERSE(CAST(@Slot   AS BINARY(2))) AS BINARY(2))

SQL 서버 2005 대신 문서화 및 지원되지 않는 가상 열 %% LockRes %% 사용할 수 있습니다
헨릭 Holmgaard 호이어

절대 정확합니다. %% LockRes는 %%은 "올바른 방법"아니다 - SQL 서버의 이전 버전의 데이터에 qucik 더러운 수정 2008 미리 경우에만 사용
헨릭 Holmgaard 호이어

11

열이 많은 매우 큰 테이블의 중복을 제거해야하며 속도가 중요합니다. 따라서 모든 테이블에서 작동하는이 방법을 사용합니다.

delete T from 
(select Row_Number() Over(Partition By BINARY_CHECKSUM(*) order by %%physloc%% ) As RowNumber, * From MyTable) T
Where T.RowNumber > 1

9

새로운 ROW_NUMBER 함수를 확인하세요 . 다음과 같이 작동합니다.

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE

14
나는 이것이 rowid가 아닌 rownum을 대체한다고 생각합니다.
tuinstoel

9

결과 집합이 아닌 테이블 내에서 행을 고유하게 식별하려면 IDENTITY 열과 같은 것을 사용해야합니다. SQL Server 도움말에서 "IDENTITY 속성"을 참조하십시오. SQL Server는 Oracle처럼 테이블의 각 행에 대해 ID를 자동 생성하지 않으므로 고유 한 ID 열을 생성하고 쿼리에서 명시 적으로 가져와야합니다.

편집 : 결과 집합 행의 동적 번호 매기기에 대해서는 아래를 참조하십시오.하지만 Oracle의 ROWNUM과 동일 할 수 있으며 페이지의 모든 주석에서 위의 내용을 원한다고 가정합니다. SQL Server 2005 이상에서는 새로운 순위 함수 기능을 사용하여 동적 행 번호 매기기를 수행 할 수 있습니다 .

예를 들어 내 쿼리에 대해 이렇게합니다.

select row_number() over (order by rn_execution_date asc) as 'Row Number', rn_execution_date as 'Execution Date', count(*) as 'Count'
from td.run
where rn_execution_date >= '2009-05-19'
group by rn_execution_date
order by rn_execution_date asc

당신에게 줄 것입니다 :

Row Number  Execution Date           Count
----------  -----------------        -----
1          2009-05-19 00:00:00.000  280
2          2009-05-20 00:00:00.000  269
3          2009-05-21 00:00:00.000  279

동적 번호 지정 행에 대한 support.microsoft.com 의 문서도 있습니다.


ID 열은 데이터베이스가 아닌 테이블의 행을 고유하게 식별한다고 생각합니다.
tuinstoel

이것은 사실이지만 Oracle 문서에서 볼 수있는 ROWID의 정의에 맞습니다. "외부 데이터 유형 ROWID는 데이터베이스 테이블의 특정 행을 식별합니다."...하지만 내 오타 때문에 상단. :) 지적 해 주셔서 감사합니다.
Xiaofu

행 "번호"는 ROWID가 아닙니다. ROWID에는 고유 번호와 다른 행의 실제 위치가 포함됩니다. (특수 저장 기술을 사용할 때 몇 가지 예외를 제외하고) 특히,이 데이터베이스의 모든 테이블 전체의 고유 한
a_horse_with_no_name

6

답변 중 일부는 위의 것 해결할 특정 행에 대한 직접 참조의 부족,하지만 작동하지 않습니다 변화는 테이블의 다른 행에 발생합니다. 그것이 기술적으로 답이 부족한 내 기준입니다.

Oracle ROWID의 일반적인 용도는 행을 선택하고 나중에 행으로 돌아가서 처리 (예 : UPDATE)하는 (다소) 안정적인 방법을 제공하는 것입니다. 행을 찾는 방법 (복잡한 조인, 전체 텍스트 검색 또는 행 단위 검색 및 데이터에 대한 절차 테스트 적용)은 UPDATE 문을 한정하는 데 쉽고 안전하게 재사용 할 수 없습니다.

SQL Server RID는 동일한 기능을 제공하는 것처럼 보이지만 동일한 성능을 제공하지는 않습니다. 이것이 내가 보는 유일한 문제이며 불행히도 ROWID를 유지하는 목적은 매우 큰 테이블에서 행을 찾기 위해 값 비싼 작업을 반복하지 않는 것입니다. 그럼에도 불구하고 대부분의 경우 성능이 허용됩니다. Microsoft가 향후 릴리스에서 최적화 프로그램을 조정하면 성능 문제가 해결 될 수 있습니다.

FOR UPDATE를 사용하고 절차 프로그램에서 CURSOR를 열어 두는 것도 가능합니다. 그러나 이것은 대규모 또는 복잡한 일괄 처리에서 비용이 많이들 수 있습니다.

주의 사항 : 예를 들어 SELECT와 UPDATE 사이의 DBA가 물리적 행 식별자이기 때문에 데이터베이스를 재 구축하는 경우 Oracle의 ROWID조차 안정적이지 않습니다. 따라서 ROWID 장치는 범위가 잘 지정된 작업 내에서만 사용해야합니다.


3

작은 데이터 세트에 대한 기본 행 번호 지정을 원하면 이와 같은 방법은 어떻습니까?

SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees

8
rowid가 아닙니다.
Stephanie Page

그러나 ROWID가 무엇인지 모르는 일부 시청자가 찾는 빠른 추가 ID에 대해 작동합니다.
Graeme

3

에서 http://vyaskn.tripod.com/programming_faq.htm#q17 :

Oracle에는 행 번호 또는 행 ID를 사용하여 테이블의 행에 액세스하는 행 번호가 있습니다. SQL Server에 이에 상응하는 것이 있습니까? 또는 SQL Server에서 행 번호로 출력을 생성하는 방법은 무엇입니까?

SQL Server에는 Oracle의 rownum 또는 row id와 직접적으로 동등한 것이 없습니다. 엄밀히 말하면 관계형 데이터베이스에서 테이블 내의 행은 정렬되지 않으며 행 ID는 실제로 의미가 없습니다. 그러나 해당 기능이 필요한 경우 다음 세 가지 대안을 고려하십시오.

  • IDENTITY테이블에 열을 추가하십시오 .

  • 다음 쿼리를 사용하여 각 행에 대한 행 번호를 생성합니다. 다음 쿼리는 pubs 데이터베이스의 authors 테이블에있는 각 행에 대한 행 번호를 생성합니다. 이 쿼리가 작동하려면 테이블에 고유 키가 있어야합니다.

    SELECT (SELECT COUNT(i.au_id) 
            FROM pubs..authors i 
            WHERE i.au_id >= o.au_id ) AS RowID, 
           au_fname + ' ' + au_lname AS 'Author name'
    FROM          pubs..authors o
    ORDER BY      RowID
    
  • 임시 테이블 접근 방식을 사용하여 전체 결과 집합을 IDENTITY() 함수에서 생성 한 행 ID와 함께 임시 테이블에 저장합니다 . 임시 테이블을 만드는 것은 특히 큰 테이블로 작업 할 때 비용이 많이 듭니다. 테이블에 고유 키가 없으면이 방법을 사용하십시오.


3

테이블의 행에 영구적으로 번호를 지정하려면 SQL Server 용 RID 솔루션을 사용하지 마십시오. 이전 386에서 Access보다 성능이 떨어집니다. SQL Server의 경우 단순히 IDENTITY 열을 만들고 해당 열을 클러스터 된 기본 키로 사용합니다. 이렇게하면 테이블에 영구적이고 빠른 정수 B- 트리가 배치되고 더 중요한 것은 모든 비 클러스터형 인덱스가이를 사용하여 행을 찾습니다. Oracle 인 것처럼 SQL Server에서 개발하려고하면 성능이 저조한 데이터베이스가 생성됩니다. 엔진이 다른 엔진 인 척하는 것이 아니라 엔진을 최적화해야합니다.

또한 NewID ()를 사용하여 기본 키를 GUID로 채우지 마십시오. 삽입 성능이 저하됩니다. GUID를 사용해야하는 경우 NewSequentialID ()를 열 기본값으로 사용하십시오. 그러나 INT는 여전히 더 빠를 것입니다.

반면에 쿼리 결과 행에 번호를 매기려면 RowNumber Over () 함수를 쿼리 열 중 하나로 사용하십시오.




1

http://msdn.microsoft.com/en-us/library/aa260631(v=SQL.80).aspx를 참조 하십시오 . SQL 서버에서 타임 스탬프는 DateTime 열과 동일하지 않습니다. 이것은 테이블뿐만 아니라 전체 데이터베이스에서 데이터베이스의 행을 고유하게 식별하는 데 사용됩니다. 이것은 낙관적 동시성에 사용할 수 있습니다. 예 : UPDATE [Job] SET [Name] = @ Name, [XCustomData] = @ XCustomData WHERE ([ModifiedTimeStamp] = @ Original_ModifiedTimeStamp AND [GUID] = @ Original_GUID

ModifiedTimeStamp는 원래 데이터를 업데이트하고 있는지 확인하고 행에 다른 업데이트가 발생하면 실패합니다.


0

MS SQL 예제에서이 예제를 가져 왔는데 @ID가 정수 나 varchar 등으로 교환 될 수 있음을 알 수 있습니다. 이것은 내가 찾던 것과 동일한 솔루션이므로 공유하고 있습니다. 즐겨!!

-- UPDATE statement with CTE references that are correctly matched.
DECLARE @x TABLE (ID int, Stad int, Value int, ison bit);
INSERT @x VALUES (1, 0, 10, 0), (2, 1, 20, 0), (6, 0, 40, 0), (4, 1, 50, 0), (5, 3, 60, 0), (9, 6, 20, 0), (7, 5, 10, 0), (8, 8, 220, 0);
DECLARE @Error int;
DECLARE @id int;

WITH cte AS (SELECT top 1 * FROM @x WHERE Stad=6)
UPDATE x -- cte is referenced by the alias.
SET ison=1, @id=x.ID
FROM cte AS x

SELECT *, @id as 'random' from @x
GO

0

아래 주어진 방법을 사용하여 ROWID를 얻을 수 있습니다.

1. 자동 증가 필드가있는 새 테이블 만들기

2. Row_Number 분석 함수를 사용하여 요구 사항에 따라 시퀀스를 가져옵니다. 특정 필드 또는 필드 조합의 오름차순 또는 내림차순 방식으로 row_id를 원하는 상황에서 도움이되기 때문에 선호합니다.

샘플 : Row_Number () Over (Sal desc에 의한 Deptno 순서로 분할)

위 샘플은 각 부서의 최고 급여를 기준으로 일련 번호를 제공하며, 분할 기준은 선택 사항이며 요구 사항에 따라 제거 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.