Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

T-SQL Come creare tabelle dinamicamente in stored procedure?

Stai usando una variabile di tabella, ovvero dovresti dichiarare la tabella. Questa non è una tabella temporanea.

Crei una tabella temporanea in questo modo:

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

Dichiari una variabile di tabella in questo modo:

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

Si noti che una tabella temporanea viene dichiarata utilizzando # e una variabile di tabella viene dichiarata utilizzando un @.Vai a leggere la differenza tra variabili di tabella e tabelle temporanee.

AGGIORNAMENTO:

Sulla base del tuo commento di seguito, stai effettivamente tentando di creare tabelle in una procedura memorizzata. Per questo dovresti usare SQL dinamico. Fondamentalmente l'SQL dinamico consente di costruire un'istruzione SQL sotto forma di stringa e quindi eseguirla. Questo è l'UNICO modo in cui sarai in grado di creare una tabella in una procedura memorizzata. Ti mostrerò come e poi discuterò perché questa non è generalmente una buona idea.

Ora per un semplice esempio (non ho testato questo codice ma dovrebbe darti una buona indicazione su come farlo):

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

Questa procedura memorizzata può essere eseguita in questo modo:

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

Ci sono alcuni grossi problemi con questo tipo di stored procedure.

Sarà difficile soddisfare i tavoli complessi. Immagina la seguente struttura della tabella:

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 

Questa tabella è un po' più complessa del primo esempio, ma non molto. La procedura memorizzata sarà molto, molto più complessa da gestire. Quindi, sebbene questo approccio possa funzionare per i tavoli di piccole dimensioni, sarà presto ingestibile.

La creazione di tabelle richiede pianificazione. Quando crei tabelle, dovrebbero essere posizionate strategicamente su filegroup diversi. Ciò serve a garantire che non si causino conflitti di I/O del disco. Come affronterai la scalabilità se tutto viene creato nel gruppo di file principale?

Potresti chiarire perché hai bisogno di creare tabelle dinamicamente?

AGGIORNAMENTO 2:

Aggiornamento ritardato a causa del carico di lavoro. Ho letto il tuo commento sulla necessità di creare un tavolo per ogni negozio e penso che dovresti cercare di farlo come l'esempio che sto per darti.

In questo esempio faccio le seguenti ipotesi:

  1. È un sito di e-commerce che ha molti negozi
  2. Un negozio può avere molti articoli (merci) da vendere.
  3. Un articolo particolare (buono) può essere venduto in molti negozi
  4. Un negozio addebiterà prezzi diversi per articoli diversi (merci)
  5. Tutti i prezzi sono in $ (USD)

Supponiamo che questo sito di e-commerce venda console di gioco (es. Wii, PS3, XBOX360).

Guardando le mie ipotesi, vedo una classica relazione molti-a-molti. Un negozio può vendere molti articoli (merci) e gli articoli (merci) possono essere venduti in molti negozi. Dividiamolo in tabelle.

Per prima cosa avrei bisogno di un tavolo da negozio per memorizzare tutte le informazioni sul negozio.

Un semplice tavolo da negozio potrebbe assomigliare a questo:

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

Inseriamo nel database tre negozi da utilizzare durante il nostro esempio. Il codice seguente inserirà tre negozi:

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

Se esegui un SELECT * FROM Shop probabilmente vedrai quanto segue:

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

Bene, quindi ora passiamo alla tabella Articoli (merci). Poiché gli articoli/merci sono prodotti di varie aziende, chiamerò il prodotto da tavola. Puoi eseguire il codice seguente per creare una semplice tabella 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

Popoliamo la tabella dei prodotti con alcuni prodotti. Eseguire il codice seguente per inserire alcuni prodotti:

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

Se esegui SELECT * FROM Product probabilmente vedrai quanto segue:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, a questo punto hai sia le informazioni sul prodotto che sul negozio. Allora come li unisci? Bene, sappiamo che possiamo identificare il negozio dalla sua colonna chiave primaria ShopID e sappiamo che possiamo identificare un prodotto dalla sua colonna chiave primaria ProductID. Inoltre, poiché ogni negozio ha un prezzo diverso per ogni prodotto, dobbiamo memorizzare il prezzo che il negozio addebita per il prodotto.

Quindi abbiamo una tabella che associa lo Shop al prodotto. Chiameremo questo tavolo ShopProduct. Una versione semplice di questa tabella potrebbe assomigliare a questa:

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

Quindi supponiamo che il negozio American Games R Us venda solo console americane, Europe Gaming Experience venda tutte le console e Asian Games Emporium venda solo console asiatiche. Avremmo bisogno di mappare le chiavi primarie dal negozio e dalle tabelle dei prodotti nella tabella ShopProduct.

Ecco come faremo la mappatura. Nel mio esempio, American Games R Us ha un valore ShopID di 1 (questo è il valore della chiave primaria) e posso vedere che l'XBOX360 ha un valore di 3 e il negozio ha elencato l'XBOX360 per $ 159,99

Eseguendo il seguente codice completeresti la mappatura:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Ora vogliamo aggiungere tutti i prodotti al negozio Europe Gaming Experience. In questo esempio sappiamo che il negozio Europe Gaming Experience ha uno ShopID di 3 e poiché vende tutte le console dovremo inserire ProductID 1, 2 e 3 nella tabella di mappatura. Supponiamo che i prezzi delle console (prodotti) nel negozio Europe Gaming Experience siano i seguenti:1- La PS3 viene venduta a $ 259,99 , 2- La Wii viene venduta a $ 159,99 , 3- La XBOX360 viene venduta a $ 199,99.

Per ottenere questa mappatura è necessario eseguire il seguente codice:

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

A questo punto hai mappato due negozi e i loro prodotti nella tabella di mappatura. OK, quindi ora come faccio a riunire tutto questo per mostrare a un utente che naviga nel sito web? Supponiamo che tu voglia mostrare tutto il prodotto per l'esperienza di gioco europea a un utente su una pagina web:dovrai eseguire la seguente query:

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

Probabilmente vedrai i seguenti risultati:

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

Ora per un ultimo esempio, supponiamo che il tuo sito web abbia una funzione che trova il prezzo più basso per una console. Un utente chiede di trovare i prezzi più economici per XBOX360.

Puoi eseguire la seguente query:

 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

Questa query restituirà un elenco di tutti i negozi che vendono prima l'XBOX360 con il negozio più economico e così via.

Noterai che non ho aggiunto il negozio di giochi asiatici. Come esercizio, aggiungi il negozio di giochi asiatico alla tabella di mappatura con i seguenti prodotti:l'Asian Games Emporium vende la console per giochi Wii a $ 99,99 e la console PS3 a $ 159,99. Se segui questo esempio, ora dovresti capire come modellare una relazione molti-a-molti.

Spero che questo ti aiuti nei tuoi viaggi con la progettazione di database.