1

SQL Server 2005 を使用して、複数の行を挿入し、特定のフィールドをインクリメントする簡単な方法はありますか?

注、列を含むソリューションを探しているわけidentityではありません-説明については、質問の下部を参照してください

(次のスキーマとデータは、この SQLFiddleに複製されています。)

たとえば、次のテーブルとデータを考えてみましょう...

CREATE TABLE #TEMPTABLE (
   [PKID] INT IDENTITY, [FKID] INT, [MYTEXT] VARCHAR(10), [SEQUENCE] INT
)
INSERT INTO #TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE]) VALUES (1, 'one', 1)
INSERT INTO #TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE]) VALUES (1, 'two', 2)

-- Table data
PKID  FKID  MYTEXT  SEQUENCE
1     1     one     1
2     1     two     2

そして、挿入する次のデータ...

DECLARE @FKID INT
SET @FKID = 1
DECLARE @NEWDATA XML
SET @NEWDATA = '<data><text>three</text><text>four</text></data>'

SEQUENCE次のように、フィールドが現在1,2,3,4の の代わりに のように表示されるように記述できます1,2,3,3か?

INSERT INTO #TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE])
SELECT @FKID, 
       X.value('.','VARCHAR(10)'),
       (SELECT ISNULL(MAX([SEQUENCE]),0)+1 FROM #TEMPTABLE WHERE [FKID]=@FKID)
FROM @NEWDATA.nodes('/data/text') AS X(X)

-- Actual result...
PKID  FKID  MYTEXT  SEQUENCE
1     1     one     1
2     1     two     2
3     1     three   3
4     1     four    3  <-- Issue

-- Required result...
PKID  FKID  MYTEXT  SEQUENCE
1     1     one     1
2     1     two     2
3     1     three   3
4     1     four    4

アップデート:

@marc_s のコメントに応えて...

Identity は 2005 年の最善の解決策です... 断然最良の解決策です。(重複などを引き起こすすべてのリスクを伴います....)

問題のテーブルには複数のSEQUENCE値のセットが保持され、各「セット」は値に基づいていFKIDます...したがって、テーブルはこれらの行に沿ってデータを保持できます...

PKID  FKID  MYTEXT  SEQUENCE
1     1     one     1
2     1     two     2
3     1     three   3
4     1     four    4
5     2     ett     1
6     2     tva     2
7     2     tre     3
4

3 に答える 3

4

2005 でテストすることはできませんが、CTE を使用して番号を付けることができるはずです。

DECLARE @FKID INT
SET @FKID = 1
DECLARE @NEWDATA XML
SET @NEWDATA = '<data><text>three</text><text>four</text><text>five</text></data>'

;WITH cte AS (SELECT @FKID FKID, X.value('.','VARCHAR(10)') a, 
                  ROW_NUMBER() OVER (ORDER BY X) r
             FROM @NEWDATA.nodes('/data/text') AS X(X))
INSERT INTO TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE])
SELECT fkid, a,
  (SELECT ISNULL(MAX([SEQUENCE]),0)+r FROM TEMPTABLE WHERE [FKID]=cte.fkid)
FROM cte;

SELECT * FROM TEMPTABLE;

結果は次のとおりです。

1    1    one     1
2    1    two     2
3    1    three   3
4    1    four    4
5    1    five    5

アップデート

クエリが FKID を 1 つだけ挿入する場合は、次の簡略化されたバージョンも機能します (現在のクエリに必要な変更が強調表示されています)。

INSERT INTO #TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE])
SELECT @FKID, 
       X.value('.','VARCHAR(10)'),
       (SELECT ISNULL(MAX([SEQUENCE]),0)+1 FROM #TEMPTABLE WHERE [FKID]=@FKID)
        + ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM @NEWDATA.nodes('/data/text') AS X(X)

's句のの目的は(SELECT 1)、特定の順序を指定しないようにすることです。必要に応じて、別のもの (例: ) に変更できます。ROW_NUMBERORDER BYX.value('.','VARCHAR(10)'

于 2013-03-20T18:05:36.317 に答える
1

どうですか

    INSERT INTO #TEMPTABLE ([FKID], [MYTEXT], [SEQUENCE])
    SELECT @FKID, 
               X.value('.','VARCHAR(10)'),
              (SELECT ISNULL(Count(*),0)+1 FROM #TEMPTABLE)
    FROM @NEWDATA.nodes('/data/text') AS X(X)
于 2013-03-20T17:15:10.143 に答える
0

これを試して:

with data as (
  select * from ( values
    (1,1,'one'),
    (2,1,'two'),
    (3,1,'three'),
    (5,1,'five'),
    (6,1,'six')
  ) data(PKID, FKID, MYTEXT)
) 
select lhs.*, sequence = count(*)
from data lhs
left join data rhs on rhs.FKID = lhs.FKID 
  and rhs.PKID <= lhs.PKID
group by 
  lhs.PKID,
  lhs.FKID,
  lhs.MYTEXT

これをもたらします:

PKID        FKID        MYTEXT sequence
----------- ----------- ------ -----------
1           1           one    1
2           1           two    2
3           1           three  3
5           1           five   4
6           1           six    5
于 2013-03-20T17:30:58.553 に答える