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

T-SQL Hvordan opretter man tabeller dynamisk i lagrede procedurer?

Du bruger en tabelvariabel, dvs. du skal erklære tabellen. Dette er ikke en midlertidig tabel.

Du opretter en midlertidig tabel som sådan:

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

Du erklærer en tabelvariabel som sådan:

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

Bemærk, at en midlertidig tabel er erklæret ved hjælp af #, og en tabelvariabel er erklæret ved hjælp af en @. Læs om forskellen mellem tabelvariable og midlertidige tabeller.

OPDATERING:

Baseret på din kommentar nedenfor forsøger du faktisk at oprette tabeller i en lagret procedure. Til dette skal du bruge dynamisk SQL. Grundlæggende giver dynamisk SQL dig mulighed for at konstruere en SQL-sætning i form af en streng og derefter udføre den. Dette er den ENESTE måde, du vil være i stand til at oprette en tabel i en lagret procedure. Jeg vil vise dig hvordan og derefter diskutere, hvorfor dette generelt ikke er en god idé.

Nu til et simpelt eksempel (jeg har ikke testet denne kode, men den burde give dig en god indikation af, hvordan du gør det):

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

Denne lagrede procedure kan udføres således:

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

Der er nogle store problemer med denne type lagret procedure.

Det bliver svært at tage højde for komplekse borde. Forestil dig følgende tabelstruktur:

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 

Denne tabel er lidt mere kompleks end det første eksempel, men ikke meget. Den lagrede procedure vil være meget, meget mere kompleks at håndtere. Så selvom denne tilgang kan fungere for små borde, vil den hurtigt være uoverskuelig.

At lave tabeller kræver planlægning. Når du opretter tabeller, skal de placeres strategisk på forskellige filgrupper. Dette er for at sikre, at du ikke forårsager disk I/O-konflikt. Hvordan vil du adressere skalerbarhed, hvis alt er oprettet på den primære filgruppe?

Kan du afklare, hvorfor du har brug for, at tabeller skal oprettes dynamisk?

OPDATERING 2:

Forsinket opdatering på grund af arbejdsbelastning. Jeg læste din kommentar om, at du skal lave et bord til hver butik, og jeg synes, du skal se på at gøre det som det eksempel, jeg er ved at give dig.

I dette eksempel gør jeg følgende antagelser:

  1. Det er en e-handelsside, der har mange butikker
  2. En butik kan have mange varer (varer) at sælge.
  3. En bestemt vare (god) kan sælges i mange butikker
  4. En butik vil opkræve forskellige priser for forskellige varer (varer)
  5. Alle priser er i $ (USD)

Lad os sige, at denne e-handelsside sælger spillekonsoller (dvs. Wii, PS3, XBOX360).

Når jeg ser på mine antagelser, ser jeg et klassisk mange-til-mange forhold. En butik kan sælge mange varer (varer), og varer (varer) kan sælges i mange butikker. Lad os opdele dette i tabeller.

Først skulle jeg bruge et butiksbord til at gemme alle oplysninger om butikken.

Et simpelt butiksbord kan se sådan ud:

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

Lad os indsætte tre butikker i databasen til brug i vores eksempel. Følgende kode vil indsætte tre butikker:

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

Hvis du udfører en SELECT * FROM Shop du vil sandsynligvis se følgende:

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

Okay, så lad os nu gå videre til tabellen Varer (varer). Da varerne/varerne er produkter fra forskellige virksomheder, vil jeg kalde bordet for produkt. Du kan udføre følgende kode for at oprette en simpel produkttabel.

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

Lad os udfylde produkttabellen med nogle produkter. Udfør følgende kode for at indsætte nogle produkter:

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

Hvis du udfører SELECT * FROM Product du vil sandsynligvis se følgende:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, på dette tidspunkt har du både produkt- og butiksoplysninger. Så hvordan bringer du dem sammen? Vi ved godt, at vi kan identificere butikken ved dens ShopID primære nøglekolonne, og vi ved, at vi kan identificere et produkt ved dens ProductID primære nøglekolonne. Da hver butik har en forskellig pris for hvert produkt, skal vi også gemme prisen, som butikken opkræver for produktet.

Så vi har en tabel, der kortlægger Shoppen til produktet. Vi kalder dette bord ShopProduct. En simpel version af denne tabel kan se sådan ud:

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

Så lad os antage, at American Games R Us-butikken kun sælger amerikanske konsoller, Europe Gaming Experience sælger alle konsoller, og Asian Games Emporium sælger kun asiatiske konsoller. Vi skal kortlægge de primære nøgler fra butiks- og produkttabellerne til ShopProduct-tabellen.

Her er hvordan vi skal lave kortlægningen. I mit eksempel har American Games R Us en ShopID-værdi på 1 (dette er den primære nøgleværdi), og jeg kan se, at XBOX360 har en værdi på 3, og at butikken har angivet XBOX360 til $159,99

Ved at udføre følgende kode vil du fuldføre tilknytningen:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Nu vil vi tilføje alle produkter til Europe Gaming Experience-butikken. I dette eksempel ved vi, at Europe Gaming Experience-butikken har et ShopID på 3, og da den sælger alle konsoller, bliver vi nødt til at indsætte ProductID 1, 2 og 3 i kortlægningstabellen. Lad os antage, at priserne for konsollerne (produkterne) i Europe Gaming Experience-butikken er som følger:1- PS3 sælges for $259,99, 2- Wii sælges for $159,99, 3- XBOX360 sælges for $199,99.

For at få denne kortlægning udført, skal du udføre følgende kode:

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

På dette tidspunkt har du kortlagt to butikker og deres produkter i kortlægningstabellen. OK, så hvordan samler jeg det hele for at vise en bruger, der browser på webstedet? Lad os sige, at du vil vise hele produktet til European Gaming Experience til en bruger på en webside – du skal udføre følgende forespørgsel:

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

Du vil sandsynligvis se følgende resultater:

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

Nu til et sidste eksempel, lad os antage, at dit websted har en funktion, som finder den billigste pris for en konsol. En bruger beder om at finde de billigste priser på XBOX360.

Du kan udføre følgende forespørgsel:

 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

Denne forespørgsel vil returnere en liste over alle butikker, der sælger XBOX360 med den billigste butik først og så videre.

Du vil bemærke, at jeg ikke har tilføjet Asian Games-butikken. Som en øvelse kan du tilføje den asiatiske spilbutik til kortlægningstabellen med følgende produkter:Asian Games Emporium sælger Wii-spilkonsollen for $99,99 og PS3-konsollen for $159,99. Hvis du arbejder gennem dette eksempel, bør du nu forstå, hvordan du modellerer et mange-til-mange forhold.

Jeg håber, at dette hjælper dig på dine rejser med databasedesign.



  1. Sådan omdøbes en kolonne i SQL

  2. Opdel IPv4-adresse i 4 numre i Oracle sql

  3. Bash-script til at indsætte værdier i MySQL

  4. Sådan opdeles forespørgselsvindue i SQL Server Management Studio (SSMS) - SQL Server / TSQL selvstudie del 13