Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

T-SQL Como criar tabelas dinamicamente em procedimentos armazenados?


Você está usando uma variável de tabela, ou seja, você deve declarar a tabela. Esta não é uma tabela temporária.

Você cria uma tabela temporária assim:
CREATE TABLE #customer
(
     Name varchar(32) not null
)

Você declara uma variável de tabela assim:
DECLARE @Customer TABLE
(
      Name varchar(32) not null
)

Observe que uma tabela temporária é declarada usando # e uma variável de tabela é declarada usando uma leitura @.Go sobre a diferença entre variáveis ​​de tabela e tabelas temporárias.

ATUALIZAÇÃO:

Com base no seu comentário abaixo, você está realmente tentando criar tabelas em um procedimento armazenado. Para isso, você precisaria usar SQL dinâmico. Basicamente, o SQL dinâmico permite que você construa uma instrução SQL na forma de uma string e depois a execute. Esta é a ÚNICA maneira de criar uma tabela em um procedimento armazenado. Vou mostrar como e depois discutir por que isso geralmente não é uma boa ideia.

Agora, para um exemplo simples (não testei este código, mas deve dar uma boa indicação de como fazê-lo):
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 '[email protected] + '( '[email protected]+' '[email protected] +' '[email protected] +') ON PRIMARY '

   EXEC (@SQLString)
   GO

Este procedimento armazenado pode ser executado assim:

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

Existem alguns problemas importantes com esse tipo de procedimento armazenado.

Vai ser difícil atender a tabelas complexas. Imagine a seguinte estrutura de tabela:
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 

Esta tabela é um pouco mais complexa que o primeiro exemplo, mas não muito. O procedimento armazenado será muito, muito mais complexo de lidar. Portanto, embora essa abordagem possa funcionar para tabelas pequenas, rapidamente se tornará incontrolável.

A criação de tabelas requer planejamento. Ao criar tabelas, elas devem ser colocadas estrategicamente em diferentes grupos de arquivos. Isso é para garantir que você não cause contenção de E/S de disco. Como você abordará a escalabilidade se tudo for criado no grupo de arquivos primário?

Você poderia esclarecer por que você precisa que as tabelas sejam criadas dinamicamente?

ATUALIZAÇÃO 2:

Atualização atrasada devido à carga de trabalho. Li seu comentário sobre a necessidade de criar uma tabela para cada loja e acho que você deveria fazer isso como o exemplo que estou prestes a dar.

Neste exemplo, faço as seguintes suposições:
  1. É um site de comércio eletrônico que tem muitas lojas
  2. Uma loja pode ter muitos itens (bens) para vender.
  3. Um determinado item (bom) pode ser vendido em muitas lojas
  4. Uma loja cobrará preços diferentes para diferentes itens (bens)
  5. Todos os preços estão em $ (USD)

Digamos que este site de comércio eletrônico venda consoles de jogos (ou seja, Wii, PS3, XBOX360).

Olhando para minhas suposições, vejo um relacionamento clássico de muitos para muitos. Uma loja pode vender muitos itens (bens) e itens (bens) podem ser vendidos em muitas lojas. Vamos dividir isso em tabelas.

Primeiro eu precisaria de uma mesa de loja para armazenar todas as informações sobre a loja.

Uma tabela de loja simples pode ser assim:
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

Vamos inserir três lojas no banco de dados para usar durante nosso exemplo. O código a seguir irá inserir três lojas:
INSERT INTO Shop
SELECT 'American Games R US'
UNION
SELECT 'Europe Gaming Experience'
UNION
SELECT 'Asian Games Emporium'

Se você executar um SELECT * FROM Shop você provavelmente verá o seguinte:
ShopID  ShopName
1           American Games R US
2           Asian Games Emporium
3           Europe Gaming Experience

Certo, então agora vamos passar para a tabela Itens (bens). Como os itens/bens são produtos de várias empresas, vou chamar a tabela de produto. Você pode executar o código a seguir para criar uma tabela Product simples.
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

Vamos preencher a tabela de produtos com alguns produtos. Execute o seguinte código para inserir alguns produtos:
INSERT INTO Product
SELECT 'Wii'
UNION 
SELECT 'PS3'
UNION 
SELECT 'XBOX360'

Se você executar SELECT * FROM Product você provavelmente verá o seguinte:
ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, neste momento você tem informações do produto e da loja. Então, como juntá-los? Bem, sabemos que podemos identificar a loja por sua coluna de chave primária ShopID e sabemos que podemos identificar um produto por sua coluna de chave primária ProductID. Além disso, como cada loja tem um preço diferente para cada produto, precisamos armazenar o preço que a loja cobra pelo produto.

Então temos uma tabela que mapeia a Loja para o produto. Chamaremos esta tabela de ShopProduct. Uma versão simples desta tabela pode ser assim:
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

Então vamos supor que a loja American Games R Us vende apenas consoles americanos, a Europe Gaming Experience vende todos os consoles e o Asian Games Emporium vende apenas consoles asiáticos. Precisaríamos mapear as chaves primárias das tabelas shop e product na tabela ShopProduct.

Aqui está como vamos fazer o mapeamento. No meu exemplo, o American Games R Us tem um valor ShopID de 1 (este é o valor da chave primária) e posso ver que o XBOX360 tem um valor de 3 e a loja listou o XBOX360 por $ 159,99

Ao executar o código a seguir, você concluiria o mapeamento:
INSERT INTO ShopProduct VALUES(1,3,159.99)

Agora queremos adicionar todos os produtos à loja Europe Gaming Experience. Neste exemplo, sabemos que a loja da Europe Gaming Experience tem um ShopID de 3 e, como vende todos os consoles, precisaremos inserir o ProductID 1, 2 e 3 na tabela de mapeamento. Vamos supor que os preços dos consoles (produtos) na loja Europe Gaming Experience sejam os seguintes:1- O PS3 é vendido por $ 259,99 , 2- O Wii é vendido por $ 159,99 , 3- O XBOX360 é vendido por $ 199,99.

Para fazer esse mapeamento, você precisaria executar o seguinte código:
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

Neste ponto, você mapeou duas lojas e seus produtos na tabela de mapeamento. OK, então agora como faço para reunir tudo isso para mostrar um usuário navegando no site? Digamos que você queira mostrar todo o produto da European Gaming Experience para um usuário em uma página da web – você precisaria executar a seguinte consulta:
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

Você provavelmente verá os seguintes resultados:
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

Agora, para um último exemplo, vamos supor que seu site tenha um recurso que encontre o preço mais barato para um console. Um usuário pede para encontrar os preços mais baratos para o XBOX360.

Você pode executar a seguinte consulta:
 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

Esta consulta retornará uma lista de todas as lojas que vendem o XBOX360 com a loja mais barata primeiro e assim por diante.

Você notará que não adicionei a loja de Jogos Asiáticos. Como exercício, adicione a loja de jogos asiáticos à tabela de mapeamento com os seguintes produtos:o Asian Games Emporium vende o console de jogos Wii por US$ 99,99 e o console PS3 por US$ 159,99. Se você trabalhar com este exemplo, agora deve entender como modelar um relacionamento muitos-para-muitos.

Espero que isso ajude você em suas viagens com design de banco de dados.