sql >> Databasteknik >  >> RDS >> Sqlserver

T-SQL Hur skapar man tabeller dynamiskt i lagrade procedurer?

Du använder en tabellvariabel, dvs du bör deklarera tabellen. Detta är inte en tillfällig tabell.

Du skapar en tillfällig tabell så här:

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

Du deklarerar en tabellvariabel så här:

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

Lägg märke till att en temporär tabell deklareras med # och en tabellvariabel deklareras med en @. Läs om skillnaden mellan tabellvariabler och temporära tabeller.

UPPDATERING:

Baserat på din kommentar nedan försöker du faktiskt skapa tabeller i en lagrad procedur. För detta skulle du behöva använda dynamisk SQL. I grund och botten låter dynamisk SQL dig konstruera en SQL-sats i form av en sträng och sedan exekvera den. Detta är det ENDA sättet du kommer att kunna skapa en tabell i en lagrad procedur. Jag ska visa dig hur och sedan diskutera varför detta generellt sett inte är en bra idé.

Nu för ett enkelt exempel (jag har inte testat den här koden men den borde ge dig en bra indikation på hur 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

Denna lagrade procedur kan utföras så här:

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

Det finns några stora problem med denna typ av lagrad procedur.

Det kommer att bli svårt att tillgodose komplexa bord. Föreställ dig följande tabellstruktur:

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 

Den här tabellen är lite mer komplex än det första exemplet, men inte mycket. Den lagrade proceduren kommer att vara mycket, mycket mer komplex att hantera. Så även om det här tillvägagångssättet kan fungera för små bord kommer det snabbt att bli ohanterligt.

Att skapa tabeller kräver planering. När du skapar tabeller bör de placeras strategiskt på olika filgrupper. Detta för att säkerställa att du inte orsakar disk I/O-konflikt. Hur kommer du att hantera skalbarhet om allt skapas på den primära filgruppen?

Kan du förtydliga varför du behöver skapa tabeller dynamiskt?

UPPDATERING 2:

Försenad uppdatering på grund av arbetsbelastning. Jag läste din kommentar om att du måste skapa ett bord för varje butik och jag tycker att du ska se på att göra det som det exempel jag ska ge dig.

I det här exemplet gör jag följande antaganden:

  1. Det är en e-handelssida som har många butiker
  2. En butik kan ha många varor (varor) att sälja.
  3. En viss vara (bra) kan säljas i många butiker
  4. En butik tar olika priser för olika varor (varor)
  5. Alla priser är i $ (USD)

Låt säga att den här e-handelssidan säljer spelkonsoler (d.v.s. Wii, PS3, XBOX360).

När jag tittar på mina antaganden ser jag ett klassiskt många-till-många-förhållande. En butik kan sälja många varor (varor) och varor (varor) kan säljas i många butiker. Låt oss dela upp detta i tabeller.

Först skulle jag behöva ett butiksbord för att lagra all information om butiken.

Ett enkelt butiksbord kan se ut så här:

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

Låt oss infoga tre butiker i databasen att använda under vårt exempel. Följande kod kommer att infoga tre butiker:

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

Om du kör en SELECT * FROM Shop du kommer förmodligen att se följande:

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

Okej, så nu går vi vidare till tabellen Artiklar (varor). Eftersom varorna/varorna är produkter från olika företag kommer jag att kalla bordet för produkt. Du kan köra följande kod för att skapa en enkel produkttabell.

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

Låt oss fylla i produkttabellen med några produkter. Kör följande kod för att infoga vissa produkter:

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

Om du kör SELECT * FROM Product du kommer förmodligen att se följande:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, vid det här laget har du både produkt- och butiksinformation. Så hur sammanför du dem? Tja, vi vet att vi kan identifiera butiken genom dess ShopID-primärnyckelkolumn och vi vet att vi kan identifiera en produkt genom dess ProductID-primärnyckelkolumn. Dessutom, eftersom varje butik har olika pris för varje produkt måste vi lagra priset som butiken tar ut för produkten.

Så vi har en tabell som mappar butiken till produkten. Vi kommer att kalla det här bordet ShopProduct. En enkel version av den här tabellen kan se ut så här:

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å låt oss anta att American Games R Us-butiken bara säljer amerikanska konsoler, Europe Gaming Experience säljer alla konsoler och Asian Games Emporium säljer bara asiatiska konsoler. Vi skulle behöva mappa de primära nycklarna från butiken och produkttabellerna till ShopProduct-tabellen.

Här är hur vi ska göra kartläggningen. I mitt exempel har American Games R Us ett ShopID-värde på 1 (detta är det primära nyckelvärdet) och jag kan se att XBOX360 har ett värde på 3 och butiken har listat XBOX360 för $159,99

Genom att köra följande kod skulle du slutföra mappningen:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Nu vill vi lägga till alla produkter i Europe Gaming Experience-butiken. I det här exemplet vet vi att Europe Gaming Experience-butiken har ett ShopID på 3 och eftersom den säljer alla konsoler kommer vi att behöva infoga ProductID 1, 2 och 3 i mappningstabellen. Låt oss anta att priserna för konsolerna (produkterna) i Europe Gaming Experience-butiken är följande:1- PS3 säljs för 259,99 USD, 2- Wii säljs för 159,99 USD, 3- XBOX360 säljs för 199,99 USD.

För att få denna mappning gjord skulle du behöva köra följande kod:

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

Vid det här laget har du kartlagt två butiker och deras produkter i kartläggningstabellen. OK, så hur sammanför jag allt detta för att visa en användare som surfar på webbplatsen? Låt oss säga att du vill visa alla produkter för European Gaming Experience för en användare på en webbsida – du skulle behöva utföra följande fråga:

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 kommer förmodligen att se följande resultat:

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 till ett sista exempel, låt oss anta att din webbplats har en funktion som hittar det billigaste priset för en konsol. En användare frågar efter de billigaste priserna för XBOX360.

Du kan utföra följande fråga:

 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

Denna fråga kommer att returnera en lista över alla butiker som säljer XBOX360 med den billigaste butiken först och så vidare.

Du kommer att märka att jag inte har lagt till Asian Games-butiken. Som en övning kan du lägga till den asiatiska spelbutiken i karttabellen med följande produkter:Asian Games Emporium säljer Wii-spelkonsolen för $99,99 och PS3-konsolen för $159,99. Om du arbetar igenom det här exemplet bör du nu förstå hur man modellerar en många-till-många-relation.

Jag hoppas att detta hjälper dig på dina resor med databasdesign.



  1. Hur man ansluter en databas med en Amazon VPC

  2. Förstå Android.coms självstudie för att spara data i SQL-databaser

  3. Hur gör jag för att php ska fungera med postgresql?

  4. Hur kan jag komma runt MySQL Errcode 13 med SELECT INTO OUTFILE?