복붙노트

[SQL] T-SQL은 어떻게 저장 프로 시저에서 동적으로 테이블을 만드는 방법?

SQL

T-SQL은 어떻게 저장 프로 시저에서 동적으로 테이블을 만드는 방법?

다음과 같은 코드 만의 잘못 :

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

당신은 어떻게 처리 방법을 가르쳐 주시겠습니까? 정말 저를 괴롭게.

해결법

  1. ==============================

    1.당신은 즉 테이블을 선언해야 테이블 변수를 사용하고 있습니다. 이는 임시 테이블이 아닙니다.

    당신은 즉 테이블을 선언해야 테이블 변수를 사용하고 있습니다. 이는 임시 테이블이 아닙니다.

    당신과 같이 임시 테이블을 만들 :

    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 '고객', '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 :

    때문에 작업 부하에 업데이 트를 지연. 나는 각 가게 테이블을 생성 할 필요에 대한 의견을 읽고 난 당신이 내가 당신을 제공하는 대한 생각의 예처럼 그 일을 봐야한다 생각합니다.

    이 예에서 나는 다음과 같은 가정을 :

    이 전자 상거래 사이트가 게임을 콘솔 (즉 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
    

    데이터베이스에 세 개의 상점 삽입의 우리의 예 중에 사용할 수 있습니다. 다음 코드는 세 개의 상점을 삽입합니다 :

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

    당신이 가게에서 SELECT *를 실행하면 당신은 아마 다음과 같이 표시됩니다

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

    오른쪽, 그래서 지금의이 항목 (제품) 테이블로 이동하자. 항목 이후 / 제품은 여러 회사의 제품이 나는 테이블 제품을 호출하기 위하여려고하고있다. 당신은 간단한 제품 테이블을 만들려면 다음 코드를 실행할 수 있습니다.

    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
    

    하자 어떤 제품과 제품 테이블을 채 웁니다. 일부 제품을 삽입하려면 다음 코드를 실행합니다 :

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

    당신이 제품에서 선택 *를 실행하면 당신은 아마 다음과 같이 표시됩니다

    ProductID   ProductDescription
    1           PS3
    2           Wii
    3           XBOX360
    

    OK,이 시점에서 당신은 두 제품 및 매장 정보가 있습니다. 그렇다면 둘을 가지고 있습니까? 그런데 우리는 우리가 ShopID 기본 키 컬럼으로 가게를 식별 할 수 있습니다 알고 우리는 우리의 제품 ID 기본 키의 열을 기준으로 제품을 식별 할 수있는 것을 알고있다. 각 상점은 각 제품에 대해 다른 가격을 가지고 있기 때문에 또한, 우리는 가격을 제품의 가게 요금을 저장해야합니다.

    그래서 우리는 제품에 숍을 매핑하는 테이블이 있습니다. 우리는이 테이블 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
    

    그럼 미국의 게임 R 저희 가게는 미국의 콘솔을 판매하고 가정하자, 유럽 게임 경험은 모든 콘솔과 아시안 게임 백화점은 아시아 콘솔을 판매하고 판매하고있다. 우리는 ShopProduct 테이블에 가게 및 제품 테이블에서 기본 키를 매핑해야합니다.

    여기에 우리가지도를 어떻게 할 건데 방법이다. 내 예에서 미국의 게임 R 우리는 하나의 ShopID 값을 (이 기본 키 값이다)이 있고 나는 XBOX360 3의 값을 갖는 것을 볼 수 있고, 상점 $ 159.99의 XBOX360을 나열하고있다

    다음 코드를 실행함으로써 당신은 매핑을 완료 할 것입니다 :

    INSERT INTO ShopProduct VALUES(1,3,159.99)
    

    이제 우리는 유럽 게임 경험 가게에있는 모든 제품을 추가하려 할 수 있습니다. 이 예에서 우리는 유럽 게임 경험 가게 세의 ShopID을 가지고 있음을 알고는 모든 콘솔을 판매하고 있기 때문에 우리는 매핑 테이블에 제품 ID 1, 2, 3을 삽입해야합니다. 하자는 다음과 유럽 게임 경험 가게에서 콘솔 (제품)의 가격은 가정 : 1 PS3의는 $ 259.99에 판매 2 닌텐도는 $ 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
    

    이 시점에서 당신은 매핑 테이블에 두 개의 상점과 제품을 매핑 한. OK, 이제 어떻게 웹 사이트를 탐색하는 사용자를 보여주기 위해 모두 함께이 문제를 가지고 있습니까? 하자 당신이 웹 페이지에서 사용자에게 모두에게 유럽의 게임 경험을 위해 제품을 보여주고 싶은 말 - 다음 쿼리를 실행해야합니다 :

    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을 판매하는 모든 상점의 목록을 반환합니다.

    당신은 내가 아시안 게임 상점을 추가하지 않은 것을 알 수 있습니다. 연습으로, 아시아 게임은 다음 제품과 매핑 테이블에 쇼핑을 추가 : 아시안 게임 백화점은 $ 99.99에 대한 닌텐도 게임 콘솔과 $ 159.99의 PS3 콘솔을 판매하고있다. 이 예제를 통해 작업하는 경우 당신은 지금 대다 관계를 모델링하는 방법을 이해해야합니다.

    나는이 데이터베이스 설계와 당신의 여행에 도움이되기를 바랍니다.

  2. ==============================

    2.당신은 입력에서 TABLE 문을 만든 다음 그것을 실행 빌드해야합니다.

    당신은 입력에서 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);
    
  3. ==============================

    3.첫번째로, 당신은 테이블 변수와 테이블을 혼합 것으로 보인다.

    첫번째로, 당신은 테이블 변수와 테이블을 혼합 것으로 보인다.

    어느 쪽이든, 당신은 같은 테이블의 이름으로 전달할 수 없습니다. 당신은 그렇게 동적 TSQL을 사용해야합니다.

    당신은 테이블 변수를 선언하려면 :

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

    동적 테이블이 당신의 디자인을 제안 할 수 생성하기 위해 저장 프로 시저를 만들려는 사실은 잘못된 것입니다.

  4. ==============================

    4.이 T-SQL 저장 프로 시저를 사용하여 동적으로 테이블을 생성하는 방법입니다 :

    이 T-SQL 저장 프로 시저를 사용하여 동적으로 테이블을 생성하는 방법입니다 :

    declare @cmd nvarchar(1000), @MyTableName nvarchar(100);
    set @MyTableName = 'CustomerDetails';
    set @cmd = 'CREATE TABLE dbo.' + quotename(@MyTableName, '[') + '(ColumnName1 int not null,ColumnName2 int not null);';
    

    그것을로 실행 :

    exec(@cmd);
    
  5. ==============================

    5.당신은 아래의 코드를 작성할 수 있습니다 : -

    당신은 아래의 코드를 작성할 수 있습니다 : -

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

    로 실행합니다 -

    간부 spCreateTable

  6. from https://stackoverflow.com/questions/10877407/t-sql-how-to-create-tables-dynamically-in-stored-procedures by cc-by-sa and MIT license