94

SQL Server の Oracle の RowID に相当するものは何ですか?

4

13 に答える 13

124

オラクルのドキュメントから

ROWID疑似列

データベースの行ごとに、ROWID 疑似列は行のアドレスを返します。Oracle DatabaseのROWID値には、行の検索に必要な情報が含まれています:

  • オブジェクトのデータオブジェクト番号
  • 行が存在するデータファイル内のデータブロック
  • データ ブロック内の行の位置 (最初の行は 0)
  • 行が存在するデータファイル (最初のファイルは 1)。ファイル番号は、テーブルスペースに対して相対的です。

SQL Server でこれに最も近いのは、rid3 つのコンポーネントを持つ です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))
于 2011-09-24T09:17:29.270 に答える
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の記事もあります。

于 2009-05-26T06:30:25.817 に答える
8

新しいROW_NUMBER関数を確認してください。それはこのように動作します:

SELECT ROW_NUMBER() OVER (ORDER BY EMPID ASC) AS ROWID, * FROM EMPLOYEE
于 2009-05-26T06:50:06.167 に答える
6

上記の回答のいくつかは、特定の行への直接参照がないことを回避しますが、テーブル内の他の行に変更が発生した場合は機能しません。それが、技術的に不足している答えの私の基準です。

Oracle の ROWID の一般的な用途は、行を選択し、後で行に戻って処理する (たとえば、UPDATE する) ための (ある程度) 安定した方法を提供することです。行を検索する方法 (複雑な結合、全文検索、または行ごとの参照とデータに対する手続き型テストの適用) は、UPDATE ステートメントを修飾するために簡単または安全に再利用できない場合があります。

SQL Server RID は同じ機能を提供しているように見えますが、同じパフォーマンスを提供していません。それが私が目にする唯一の問題であり、残念ながら ROWID を保持する目的は、たとえば非常に大きなテーブルで行を見つけるために高価な操作を繰り返さないようにすることです。それでも、多くの場合のパフォーマンスは許容範囲内です。Microsoft が将来のリリースでオプティマイザーを調整すると、パフォーマンスの問題が解決される可能性があります。

FOR UPDATE を単純に使用して、手続き型プログラムで CURSOR を開いたままにすることもできます。ただし、これは、大規模または複雑なバッチ処理ではコストがかかる可能性があります。

警告: DBA がたとえば SELECT と UPDATE の間でデータベースを再構築する場合、Oracle の ROWID でさえ安定しません。これは物理的な行識別子であるためです。したがって、ROWID デバイスは、適切な範囲のタスク内でのみ使用する必要があります。

于 2011-09-28T16:54:13.690 に答える
5

テーブル内の行に永続的に番号を付けたい場合は、SQL Server の RID ソリューションを使用しないでください。古い 386 では Access よりもパフォーマンスが低下します。SQL Server の場合は、単純に IDENTITY 列を作成し、その列をクラスター化された主キーとして使用します。これにより、永続的で高速な整数 B ツリーがテーブルに配置され、さらに重要なことに、すべての非クラスター化インデックスはそれを使用して行を検索します。Oracle であるかのように SQL Server で開発しようとすると、パフォーマンスの低いデータベースが作成されます。別のエンジンのふりをするのではなく、エンジンを最適化する必要があります。

また、NewID() を使用して主キーに GUID を設定しないでください。挿入のパフォーマンスが低下します。GUID を使用する必要がある場合は、カラムのデフォルトとして NewSequentialID() を使用します。しかし、INTはまだ速くなります。

一方、クエリの結果の行に番号を付けたいだけの場合は、RowNumber Over() 関数をクエリ列の 1 つとして使用します。

于 2013-09-18T20:28:07.303 に答える
4

小さなデータセットの基本的な行番号付けが必要な場合は、このようなものはどうでしょうか。

SELECT row_number() OVER (order by getdate()) as ROWID, * FROM Employees
于 2010-01-28T17:21:13.293 に答える
4

http://vyaskn.tripod.com/programming_faq.htm#q17から:

Oracle には、行番号または行 ID を使用してテーブルの行にアクセスするための rownum があります。SQL Server にこれに相当するものはありますか? または、SQL Server で行番号を使用して出力を生成する方法は?

SQL Server には、Oracle の rownum または行 ID に直接相当するものはありません。厳密に言えば、リレーショナル データベースでは、テーブル内の行は順序付けされておらず、行 ID は実際には意味がありません。ただし、その機能が必要な場合は、次の 3 つの代替案を検討してください。

  • IDENTITYテーブルに列を追加します。

  • 次のクエリを使用して、各行の行番号を生成します。次のクエリは、pubs データベースの author テーブルの各行の行番号を生成します。このクエリが機能するには、テーブルに一意のキーが必要です。

    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
    
  • 一時テーブル アプローチを使用して、関数によって生成された行 ID と共に、結果セット全体を一時テーブルに格納しIDENTITY() ます。一時テーブルを作成すると、特に大きなテーブルを扱う場合にコストがかかります。テーブルに一意のキーがない場合は、このアプローチを使用してください。

于 2009-05-26T06:22:43.913 に答える
1

ROWID は Oracle テーブルの非表示の列であるため、SQL Server の場合は独自の列を作成します。デフォルト値が の ROWID という列を追加しますNEWID()

その方法: SQL Server の既存のテーブルに列を既定値で追加します。

于 2011-09-19T02:21:40.877 に答える
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 は元のデータを更新していることを保証し、行に別の更新が発生した場合は失敗します。

于 2013-03-12T02:33:00.530 に答える
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
于 2011-09-23T18:46:39.513 に答える