14

私は2つのテーブルを持っています。一方のテーブルAには n 行のデータがあり、もう一方のテーブルBは空です。tableにinsertn 行、 tableBの各行に 1 行を追加しますA。テーブルには、テーブルからの外部キーを含む、Bテーブルからのフィールドがいくつかあります。AA

最後に、 の各行に 1 つの行が必要BですA。これを行うには、次を使用しました。

INSERT INTO B(Col1
             ,Col2
             ,Col3
             ,Col4
             ,Col5
             );
SELECT 100
      ,25 
      ,'ABC'
      ,1
      ,A.ID
FROM Auctions A

今、私はこのコードをストアド プロシージャに入れました。この SP は というintパラメータを取りますNumInserts

行を挿入したいn * NumInserts。したがって、n が 10 で NumInserts が 5 の場合、このコードを 5 * 10 (50) 回実行します。

つまり、 の各行に対して、 の5 つの行がtable A必要です。どうすればいいですか?inserttable B

4

6 に答える 6

18
create procedure insert_into_b
    @numInserts int
as
begin
    while @numInserts > 0
    begin
        insert into b (id)
        select id from a
        set @numInserts = @numInserts - 1
    end
end

exec insert_into_b 2
于 2012-11-20T15:42:37.520 に答える
10

私はできる限りループを避けることを好みます。これは、ストアド プロシージャで壊れやすくやや醜いループ構造を維持する必要がないようにするためです。

Numbersこれは、テーブル、CROSS APPLYステートメント、および既存のステートメントを使用して簡単に実行できますINSERT

数値テーブルが次のようになるとします。

Number
======
0
1
2
...

SQL ステートメントは単純に次のようになります。

INSERT INTO B 
(
    [Col1]
    ,[Col2]
    ,[Col3]
    ,[Col4]
    ,[Col5]
)
SELECT 
    100 
    ,25
    ,'ABC'
    ,1
    ,a.ID
FROM 
    Auctions a
CROSS APPLY
    Numbers n
WHERE
    n.Number BETWEEN 1 AND @NumInserts

数値表は、適切に使用すれば役立ちます。それらに慣れていない場合は、いくつかのリソースと長所/短所を次に示します。

が常に適度に小さい数値になる場合、この解決策はやり過ぎかもしれ@NumInsertsませんが、既に Numbers テーブルが存在する場合は、それを利用することもできます!

更新

以下は、0 から 65,535 までの数値テーブルを作成するための簡単で汚れた方法です。

CREATE TABLE Numbers
(
    Number INT NOT NULL,
    CONSTRAINT PK_Numbers 
        PRIMARY KEY CLUSTERED (Number)
        WITH FILLFACTOR = 100
)
GO

INSERT INTO Numbers
SELECT
    (a.Number * 256) + b.Number AS Number
FROM 
(
    SELECT number
    FROM master..spt_values
    WHERE 
        type = 'P'
        AND number <= 255
) a (Number),
(
    SELECT number
    FROM master..spt_values
    WHERE 
        type = 'P'
        AND number <= 255
) b (Number)
GO

クレジット: http://dataeducation.com/you-require-a-numbers-table/

于 2012-11-20T15:47:32.903 に答える
10

This is a hack and I wouldn't recommend using it in production or big volumes of data. However, in development quick-and-dirty scenarios I found it often useful:

Use GO \[count\] to execute a batch of commands a specified number of times.

Concretely, if you had a stored procedure called InsertAIntoB, you could run this in Management Studio:

exec InsertAIntoB
GO 10

(replace 10 with whatever NumInserts is)

于 2012-11-20T15:55:19.950 に答える
2
 Create procedure DoitNTimes 
 @N integer = 1
 As
 Set NoCount On

    While @N > 0 Begin
       Insert B (Col1, Col2, Col3, Col4, Col5)
       Select 100, 25, 'ABC', 1, A.ID
       From Auctions A
       -- -----------------------------------
       Set @N -= 1
    End

SQL Server 2005 以前を使用している場合は、Set @N -= 1' withSet @N = @N-1` を置き換えます

T-SQL変数を使用してループを本当に回避したい場合は、ディスクベースのテーブルではなくCTEを使用してください。

 Create procedure DoitNTimes 
 @N integer = 1
 As
 Set NoCount On

     With nums(num) As
       (Select @N Union All
        Select num - 1
        From nums
        Where num > 1)
     Insert B (Col1, Col2, Col3, Col4, Col5)
     Select 100, 25, 'ABC', 1, A.ID
     From Auctions A Full Join nums
     Option(MaxRecursion 10000) 

もちろん、この問題の解決策と同様に、これもまだループしています。

于 2012-11-20T15:39:35.237 に答える