SQL Server에서 Oracle의 RowID에 해당하는 것은 무엇입니까?
답변:
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_PhysLocCracker
TVF를 사용하여이를 더 읽기 쉬운 형식으로 변환 할 수 있습니다.
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))
새로운 ROW_NUMBER 함수를 확인하세요 . 다음과 같이 작동합니다.
SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
결과 집합이 아닌 테이블 내에서 행을 고유하게 식별하려면 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 의 문서도 있습니다.
답변 중 일부는 위의 것 해결할 특정 행에 대한 직접 참조의 부족,하지만 작동하지 않습니다 변화는 테이블의 다른 행에 발생합니다. 그것이 기술적으로 답이 부족한 내 기준입니다.
Oracle ROWID의 일반적인 용도는 행을 선택하고 나중에 행으로 돌아가서 처리 (예 : UPDATE)하는 (다소) 안정적인 방법을 제공하는 것입니다. 행을 찾는 방법 (복잡한 조인, 전체 텍스트 검색 또는 행 단위 검색 및 데이터에 대한 절차 테스트 적용)은 UPDATE 문을 한정하는 데 쉽고 안전하게 재사용 할 수 없습니다.
SQL Server RID는 동일한 기능을 제공하는 것처럼 보이지만 동일한 성능을 제공하지는 않습니다. 이것이 내가 보는 유일한 문제이며 불행히도 ROWID를 유지하는 목적은 매우 큰 테이블에서 행을 찾기 위해 값 비싼 작업을 반복하지 않는 것입니다. 그럼에도 불구하고 대부분의 경우 성능이 허용됩니다. Microsoft가 향후 릴리스에서 최적화 프로그램을 조정하면 성능 문제가 해결 될 수 있습니다.
FOR UPDATE를 사용하고 절차 프로그램에서 CURSOR를 열어 두는 것도 가능합니다. 그러나 이것은 대규모 또는 복잡한 일괄 처리에서 비용이 많이들 수 있습니다.
주의 사항 : 예를 들어 SELECT와 UPDATE 사이의 DBA가 물리적 행 식별자이기 때문에 데이터베이스를 재 구축하는 경우 Oracle의 ROWID조차 안정적이지 않습니다. 따라서 ROWID 장치는 범위가 잘 지정된 작업 내에서만 사용해야합니다.
작은 데이터 세트에 대한 기본 행 번호 지정을 원하면 이와 같은 방법은 어떻습니까?
SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
에서 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와 함께 임시 테이블에 저장합니다 . 임시 테이블을 만드는 것은 특히 큰 테이블로 작업 할 때 비용이 많이 듭니다. 테이블에 고유 키가 없으면이 방법을 사용하십시오.
테이블의 행에 영구적으로 번호를 지정하려면 SQL Server 용 RID 솔루션을 사용하지 마십시오. 이전 386에서 Access보다 성능이 떨어집니다. SQL Server의 경우 단순히 IDENTITY 열을 만들고 해당 열을 클러스터 된 기본 키로 사용합니다. 이렇게하면 테이블에 영구적이고 빠른 정수 B- 트리가 배치되고 더 중요한 것은 모든 비 클러스터형 인덱스가이를 사용하여 행을 찾습니다. Oracle 인 것처럼 SQL Server에서 개발하려고하면 성능이 저조한 데이터베이스가 생성됩니다. 엔진이 다른 엔진 인 척하는 것이 아니라 엔진을 최적화해야합니다.
또한 NewID ()를 사용하여 기본 키를 GUID로 채우지 마십시오. 삽입 성능이 저하됩니다. GUID를 사용해야하는 경우 NewSequentialID ()를 열 기본값으로 사용하십시오. 그러나 INT는 여전히 더 빠를 것입니다.
반면에 쿼리 결과 행에 번호를 매기려면 RowNumber Over () 함수를 쿼리 열 중 하나로 사용하십시오.
시도하십시오
select NEWID()
출처 : https://docs.microsoft.com/en-us/sql/t-sql/data-types/uniqueidentifier-transact-sql
ROWID는 Oracle 테이블의 숨겨진 열이므로 SQL Server의 경우 직접 빌드하십시오. 기본값 인 ROWID라는 열을 추가합니다 NEWID()
.
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는 원래 데이터를 업데이트하고 있는지 확인하고 행에 다른 업데이트가 발생하면 실패합니다.
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
아래 주어진 방법을 사용하여 ROWID를 얻을 수 있습니다.
1. 자동 증가 필드가있는 새 테이블 만들기
2. Row_Number 분석 함수를 사용하여 요구 사항에 따라 시퀀스를 가져옵니다. 특정 필드 또는 필드 조합의 오름차순 또는 내림차순 방식으로 row_id를 원하는 상황에서 도움이되기 때문에 선호합니다.
샘플 : Row_Number () Over (Sal desc에 의한 Deptno 순서로 분할)
위 샘플은 각 부서의 최고 급여를 기준으로 일련 번호를 제공하며, 분할 기준은 선택 사항이며 요구 사항에 따라 제거 할 수 있습니다.