sql >> Database >  >> RDS >> Sqlserver

T-SQL Hoe tabellen dynamisch te creëren in opgeslagen procedures?

U gebruikt een tabelvariabele, d.w.z. u moet de tabel declareren. Dit is geen tijdelijke tafel.

U maakt een tijdelijke tabel als volgt:

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

U declareert een tabelvariabele als volgt:

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

Merk op dat een tijdelijke tabel wordt gedeclareerd met # en een tabelvariabele wordt gedeclareerd met een @. Lees meer over het verschil tussen tabelvariabelen en tijdelijke tabellen.

UPDATE:

Op basis van uw onderstaande opmerking probeert u in feite tabellen te maken in een opgeslagen procedure. Hiervoor zou u dynamische SQL moeten gebruiken. In feite stelt dynamische SQL u in staat om een ​​SQL-instructie in de vorm van een tekenreeks te construeren en deze vervolgens uit te voeren. Dit is de ENIGE manier waarop u een tabel kunt maken in een opgeslagen procedure. Ik ga je laten zien hoe en dan bespreken waarom dit over het algemeen geen goed idee is.

Nu voor een eenvoudig voorbeeld (ik heb deze code niet getest, maar het zou je een goede indicatie moeten geven van hoe je het moet doen):

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

Deze opgeslagen procedure kan als volgt worden uitgevoerd:

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

Er zijn enkele grote problemen met dit soort opgeslagen procedures.

Het zal moeilijk worden om complexe tabellen te voorzien. Stel je de volgende tabelstructuur voor:

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 

Deze tabel is iets complexer dan het eerste voorbeeld, maar niet veel. De opgeslagen procedure zal veel, veel complexer zijn om mee om te gaan. Dus hoewel deze aanpak misschien werkt voor kleine tafels, zal het al snel onhandelbaar worden.

Het maken van tabellen vereist planning. Wanneer u tabellen maakt, moeten ze strategisch op verschillende bestandsgroepen worden geplaatst. Dit is om ervoor te zorgen dat u geen disk-I/O-conflicten veroorzaakt. Hoe ga je om met schaalbaarheid als alles in de primaire bestandsgroep wordt gemaakt?

Kunt u uitleggen waarom tabellen dynamisch moeten worden gemaakt?

UPDATE 2:

Vertraagde update vanwege werkdruk. Ik heb je opmerking gelezen over het maken van een tabel voor elke winkel en ik denk dat je het moet zien als het voorbeeld dat ik je ga geven.

In dit voorbeeld maak ik de volgende aannames:

  1. Het is een e-commercesite met veel winkels
  2. Een winkel kan veel items (goederen) verkopen.
  3. Een bepaald artikel (goed) kan in veel winkels worden verkocht
  4. Een winkel rekent verschillende prijzen voor verschillende artikelen (goederen)
  5. Alle prijzen zijn in $ (USD)

Laten we zeggen dat deze e-commercesite gameconsoles verkoopt (bijv. Wii, PS3, XBOX360).

Als ik naar mijn aannames kijk, zie ik een klassieke veel-op-veel-relatie. Een winkel kan veel artikelen (goederen) verkopen en artikelen (goederen) kunnen bij veel winkels worden verkocht. Laten we dit opsplitsen in tabellen.

Eerst zou ik een winkeltafel nodig hebben om alle informatie over de winkel op te slaan.

Een eenvoudige winkeltafel kan er als volgt uitzien:

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

Laten we drie winkels in de database invoegen om tijdens ons voorbeeld te gebruiken. De volgende code voegt drie winkels in:

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

Als u een SELECT * FROM Shop . uitvoert je zult waarschijnlijk het volgende zien:

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

Juist, dus laten we nu naar de tabel Artikelen (goederen) gaan. Aangezien de artikelen/goederen producten zijn van verschillende bedrijven ga ik het tafelproduct noemen. U kunt de volgende code uitvoeren om een ​​eenvoudige producttabel te maken.

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

Laten we de tabel met producten vullen met enkele producten. Voer de volgende code uit om enkele producten in te voegen:

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

Als u SELECT * FROM Product . uitvoert je zult waarschijnlijk het volgende zien:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, op dit punt heb je zowel product- als winkelinformatie. Dus hoe breng je ze samen? Welnu, we weten dat we de winkel kunnen identificeren aan de hand van de kolom met primaire sleutel van ShopID en we weten dat we een product kunnen identificeren aan de hand van de kolom met primaire sleutel van ProductID. Omdat elke winkel een andere prijs heeft voor elk product, moeten we ook de prijs opslaan die de winkel voor het product in rekening brengt.

We hebben dus een tabel die de winkel aan het product koppelt. We zullen deze tafel ShopProduct noemen. Een eenvoudige versie van deze tabel kan er als volgt uitzien:

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

Laten we dus aannemen dat de American Games R Us-winkel alleen Amerikaanse consoles verkoopt, de Europe Gaming Experience alle consoles en de Asian Games Emporium alleen Aziatische consoles. We zouden de primaire sleutels van de winkel- en producttabellen moeten toewijzen aan de ShopProduct-tabel.

Hier is hoe we de mapping gaan doen. In mijn voorbeeld heeft de American Games R Us een ShopID-waarde van 1 (dit is de primaire sleutelwaarde) en ik kan zien dat de XBOX360 een waarde van 3 heeft en de winkel heeft de XBOX360 vermeld voor $ 159,99

Door de volgende code uit te voeren, voltooit u de toewijzing:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Nu willen we alle producten toevoegen aan de Europe Gaming Experience-winkel. In dit voorbeeld weten we dat de Europe Gaming Experience-winkel een ShopID van 3 heeft en aangezien alle consoles worden verkocht, moeten we de ProductID 1, 2 en 3 in de toewijzingstabel invoeren. Laten we aannemen dat de prijzen voor de consoles (producten) in de Europe Gaming Experience-winkel als volgt zijn:1- De PS3 wordt verkocht voor $ 259,99 , 2- De Wii wordt verkocht voor $ 159,99 , 3- De XBOX360 wordt verkocht voor $ 199,99.

Om deze mapping voor elkaar te krijgen, moet u de volgende code uitvoeren:

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

Op dit punt heb je twee winkels en hun producten in kaart gebracht in de kaarttabel. OK, dus hoe breng ik dit nu allemaal samen om een ​​gebruiker te laten zien die op de website surft? Stel dat u alle producten voor de European Gaming Experience aan een gebruiker op een webpagina wilt laten zien, dan moet u de volgende zoekopdracht uitvoeren:

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

U zult waarschijnlijk de volgende resultaten zien:

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

Laten we nu voor een laatste voorbeeld aannemen dat uw website een functie heeft die de goedkoopste prijs voor een console vindt. Een gebruiker vraagt ​​om de goedkoopste prijzen voor XBOX360 te vinden.

U kunt de volgende query uitvoeren:

 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

Deze zoekopdracht levert een lijst op van alle winkels die de XBOX360 verkopen met eerst de goedkoopste winkel, enzovoort.

U zult merken dat ik de Asian Games-winkel niet heb toegevoegd. Voeg als oefening de Aziatische spellenwinkel toe aan de kaartentabel met de volgende producten:het Asian Games Emporium verkoopt de Wii-spelconsole voor $ 99,99 en de PS3-console voor $ 159,99. Als u dit voorbeeld doorneemt, zou u nu moeten begrijpen hoe u een veel-op-veel-relatie kunt modelleren.

Ik hoop dat dit je helpt bij je reizen met het ontwerpen van een database.



  1. Hoe lees ik de inhoud van een .sql-bestand in een R-script om een ​​query uit te voeren?

  2. 4 manieren om een ​​getal op te maken zonder decimalen in Oracle

  3. Hoe SESSION_CONTEXT() werkt in SQL Server

  4. CURRENT_DATE Voorbeelden – MySQL