21

次のようなコードですが、間違っています。

CREATE PROC sp_createATable
  @name        VARCHAR(10),
  @properties  VARCHAR(500)
AS
  CREATE TABLE @name
  (
    id  CHAR(10)  PRIMARY KEY,
    --...Properties extracted from @properties
  );

対処方法を教えていただけますか?それは本当に私を悩ませます。

4

5 に答える 5

50

テーブル変数を使用しています。つまり、テーブルを宣言する必要があります。これは一時テーブルではありません。

次のように一時テーブルを作成します。

CREATE TABLE #customer
(
     Name varchar(32) not null
)

次のようにテーブル変数を宣言します。

DECLARE @Customer TABLE
(
      Name varchar(32) not null
)

一時テーブルは # を使用して宣言され、テーブル変数は @ を使用して宣言されていることに注意してください。テーブル変数と一時テーブルの違いについて読んでください。

アップデート:

以下のコメントに基づいて、実際にストアド プロシージャでテーブルを作成しようとしています。このためには、動的 SQL を使用する必要があります。基本的に動的 SQL では、文字列の形式で SQL ステートメントを作成し、それを実行できます。これは、ストアド プロシージャでテーブルを作成できる唯一の方法です。その方法を示してから、これが一般的に良い考えではない理由について説明します。

次に簡単な例を示します (私はこのコードをテストしていませんが、その方法をよく示しているはずです)。

CREATE PROCEDURE sproc_BuildTable 
    @TableName NVARCHAR(128)
   ,@Column1Name NVARCHAR(32)
   ,@Column1DataType NVARCHAR(32)
   ,@Column1Nullable NVARCHAR(32)
AS

   DECLARE @SQLString NVARCHAR(MAX)
   SET @SQString = 'CREATE TABLE '+@TableName + '( '+@Column1Name+' '+@Column1DataType +' '+@Column1Nullable +') ON PRIMARY '

   EXEC (@SQLString)
   GO

このストアド プロシージャは、次のように実行できます。

sproc_BuildTable 'Customers','CustomerName','VARCHAR(32)','NOT NULL'

このタイプのストアド プロシージャにはいくつかの大きな問題があります。

複雑なテーブルに対応するのは難しいでしょう。次のテーブル構造を想像してください。

CREATE TABLE [dbo].[Customers] (
    [CustomerID] [int] IDENTITY(1,1) NOT NULL,
    [CustomerName] [nvarchar](64) NOT NULL,
    [CustomerSUrname] [nvarchar](64) NOT NULL,
    [CustomerDateOfBirth] [datetime] NOT NULL,
    [CustomerApprovedDiscount] [decimal](3, 2) NOT NULL,
    [CustomerActive] [bit] NOT NULL,
    CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
    (
        [CustomerID] ASC
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,      ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Customers] ADD CONSTRAINT [DF_Customers_CustomerApprovedDiscount] DEFAULT ((0.00)) FOR [CustomerApprovedDiscount]
GO 

この表は最初の例より少し複雑ですが、それほど多くはありません。ストアド プロシージャの処理は、はるかに複雑になります。したがって、このアプローチは小さなテーブルでは機能するかもしれませんが、すぐに管理できなくなります。

テーブルの作成には計画が必要です。テーブルを作成するときは、異なるファイル グループに戦略的に配置する必要があります。これは、ディスク I/O の競合が発生しないようにするためです。すべてがプライマリ ファイル グループ上に作成されている場合、スケーラビリティにどのように対処しますか?

テーブルを動的に作成する必要がある理由を明確にしていただけますか?

更新 2:

仕事の都合で更新が遅くなりました。ショップごとにテーブルを作成する必要があるというコメントを読みましたが、これから紹介する例のように作成することを検討する必要があると思います。

この例では、次の仮定を行います。

  1. ショップ数が多いECサイトです
  2. ショップは、販売する多くのアイテム (商品) を持つことができます。
  3. 特定の商品(商品)を多くの店で販売できる
  4. ショップは、アイテム (商品) ごとに異なる価格を請求します。
  5. すべての価格は $ (USD) です

この e コマース サイトがゲーム コンソール (つまり、Wii、PS3、XBOX360) を販売しているとします。

私の仮定を見ると、古典的な多対多の関係が見えます。ショップは多くのアイテム (商品) を販売でき、アイテム (グッズ) は多くのショップで販売できます。これを表に分解してみましょう。

まず、ショップに関するすべての情報を格納するためのショップ テーブルが必要です。

シンプルなショップ テーブルは次のようになります。

CREATE TABLE [dbo].[Shop](
    [ShopID] [int] IDENTITY(1,1) NOT NULL,
    [ShopName] [nvarchar](128) NOT NULL,
    CONSTRAINT [PK_Shop] PRIMARY KEY CLUSTERED 
    (
      [ShopID] ASC
    ) WITH (
              PAD_INDEX  = OFF
              , STATISTICS_NORECOMPUTE  = OFF
              , IGNORE_DUP_KEY = OFF
              , ALLOW_ROW_LOCKS  = ON
              , ALLOW_PAGE_LOCKS  = ON
    ) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

この例で使用する 3 つの店舗をデータベースに挿入してみましょう。次のコードは、3 つのショップを挿入します。

INSERT INTO Shop
SELECT 'American Games R US'
UNION
SELECT 'Europe Gaming Experience'
UNION
SELECT 'Asian Games Emporium'

a を実行する と、SELECT * FROM Shopおそらく次のように表示されます。

ShopID  ShopName
1           American Games R US
2           Asian Games Emporium
3           Europe Gaming Experience

では、Items (グッズ) テーブルに移りましょう。商品・グッズは各社の商品ですので、テーブル商品とさせていただきます。次のコードを実行して、単純な Product テーブルを作成できます。

CREATE TABLE [dbo].[Product](
    [ProductID] [int] IDENTITY(1,1) NOT NULL,
    [ProductDescription] [nvarchar](128) NOT NULL,
 CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED 
 (
     [ProductID] ASC
 )WITH (PAD_INDEX  = OFF
        , STATISTICS_NORECOMPUTE  = OFF
        , IGNORE_DUP_KEY = OFF
        ,     ALLOW_ROW_LOCKS  = ON
         , ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  ) ON [PRIMARY]

GO

products テーブルにいくつかの製品を入力してみましょう。次のコードを実行して、いくつかの製品を挿入します。

INSERT INTO Product
SELECT 'Wii'
UNION 
SELECT 'PS3'
UNION 
SELECT 'XBOX360'

実行SELECT * FROM Productすると、おそらく次のように表示されます。

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK、この時点で、製品とショップの両方の情報が得られました。では、それらをどのようにまとめますか?ShopID 主キー列でショップを識別できることはわかっていますし、ProductID 主キー列で製品を識別できることもわかっています。また、ショップごとに商品ごとに異なる価格が設定されているため、ショップが商品に対して請求する価格を保存する必要があります。

これで、Shop を製品にマップするテーブルができました。このテーブルを ShopProduct と呼びます。このテーブルの単純なバージョンは次のようになります。

CREATE TABLE [dbo].[ShopProduct](
[ShopID] [int] NOT NULL,
[ProductID] [int] NOT NULL,
[Price] [money] NOT NULL,
CONSTRAINT [PK_ShopProduct] PRIMARY KEY CLUSTERED 
 (
     [ShopID] ASC,
      [ProductID] ASC
 )WITH (PAD_INDEX  = OFF,
     STATISTICS_NORECOMPUTE  = OFF, 
     IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS  = ON,
     ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  ) ON [PRIMARY]

 GO

そこで、American Games R Us ショップがアメリカのコンソールのみを販売し、Europe Gaming Experience がすべてのコンソールを販売し、Asian Games Emporium がアジアのコンソールのみを販売していると仮定しましょう。shop テーブルと product テーブルの主キーを ShopProduct テーブルにマップする必要があります。

ここでは、マッピングを行う方法について説明します。私の例では、American Games R Us の ShopID 値は 1 (これが主キーの値です) で、XBOX360 の値は 3 で、ショップは XBOX360 を $159.99 でリストしています。

次のコードを実行すると、マッピングが完了します。

INSERT INTO ShopProduct VALUES(1,3,159.99)

ここで、すべての製品を Europe Gaming Experience ショップに追加したいと考えています。この例では、Europe Gaming Experience ショップの ShopID が 3 であることがわかっており、すべてのコンソールを販売しているため、ProductID 1、2、および 3 をマッピング テーブルに挿入する必要があります。Europe Gaming Experience ショップでのコンソール (製品) の価格を次のように仮定します。1- PS3 は $259.99 で販売され、2- Wii は $159.99 で販売され、3- XBOX360 は $199.99 で販売されています。

このマッピングを行うには、次のコードを実行する必要があります。

INSERT INTO ShopProduct VALUES(3,2,159.99) --This will insert the WII console into the mapping table for the Europe Gaming Experience Shop with a price of 159.99
INSERT INTO ShopProduct VALUES(3,1,259.99) --This will insert the PS3 console into the mapping table for the Europe Gaming Experience Shop with a price of 259.99
INSERT INTO ShopProduct VALUES(3,3,199.99) --This will insert the XBOX360 console into the mapping table for the Europe Gaming Experience Shop with a price of 199.99

この時点で、2 つのショップとその製品がマッピング テーブルにマップされました。では、これをすべてまとめて、Web サイトを閲覧しているユーザーを表示するにはどうすればよいでしょうか。European Gaming Experience のすべての製品を Web ページでユーザーに表示したいとします。次のクエリを実行する必要があります。

SELECT      Shop.*
        , ShopProduct.*
        , Product.*
FROM         Shop 
INNER JOIN  ShopProduct ON Shop.ShopID = ShopProduct.ShopID 
INNER JOIN  Product ON ShopProduct.ProductID = Product.ProductID
WHERE       Shop.ShopID=3

おそらく次の結果が表示されます。

ShopID     ShopName                 ShopID  ProductID   Price   ProductID   ProductDescription
3          Europe Gaming Experience   3         1       259.99  1           PS3
3          Europe Gaming Experience   3         2       159.99  2           Wii
3          Europe Gaming Experience   3         3       199.99  3           XBOX360

最後の例として、あなたのウェブサイトにコンソールの最安値を見つける機能があるとしましょう。ユーザーが XBOX360 の最安値を探すように依頼しました。

次のクエリを実行できます。

 SELECT     Shop.*
        , ShopProduct.*
        , Product.*
 FROM         Shop 
 INNER JOIN  ShopProduct ON Shop.ShopID = ShopProduct.ShopID 
 INNER JOIN  Product ON ShopProduct.ProductID = Product.ProductID
 WHERE      Product.ProductID =3  -- You can also use Product.ProductDescription = 'XBOX360'
 ORDER BY    Price ASC

このクエリは、XBOX360 を販売しているすべてのショップのリストを、最も安いショップから順に返します。

アジア競技大会のショップを追加していないことに気付くでしょう。演習として、次の製品を含むアジアのゲーム ショップをマッピング テーブルに追加します。Asian Games Emporium は、Wii ゲーム コンソールを 99.99 ドル、PS3 コンソールを 159.99 ドルで販売しています。この例に取り組むと、多対多の関係をモデル化する方法を理解できるはずです。

これが、データベース設計に関する旅行に役立つことを願っています。

于 2012-06-04T07:06:06.030 に答える
3

入力からその CREATE TABLE ステートメントを作成し、それを実行する必要があります。

簡単な例:

declare @cmd nvarchar(1000), @TableName nvarchar(100);

set @TableName = 'NewTable';

set @cmd = 'CREATE TABLE dbo.' + quotename(@TableName, '[') + '(newCol int not null);';

print @cmd;

--exec(@cmd);
于 2012-06-04T07:04:06.120 に答える
1

まず、テーブル変数とテーブルを混在させているようです。

いずれにせよ、そのようなテーブルの名前を渡すことはできません。これを行うには、動的 TSQL を使用する必要があります。

テーブル変数を宣言するだけの場合:

CREATE PROC sp_createATable 
  @name        VARCHAR(10), 
  @properties  VARCHAR(500) 
AS 
  declare @tablename TABLE
  ( 
    id  CHAR(10)  PRIMARY KEY 
  ); 

テーブルを動的に作成するためにストアド プロシージャを作成したいという事実は、設計が間違っていることを示唆している可能性があります。

于 2012-06-04T07:04:50.297 に答える
0

以下のコードを書くことができます:-

create procedure spCreateTable
   as
    begin
       create table testtb(Name varchar(20))
    end

次のように実行します:-

exec spCreateTable

于 2015-07-16T17:32:57.597 に答える