Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

T-SQL Wie erstelle ich Tabellen dynamisch in gespeicherten Prozeduren?

Sie verwenden eine Tabellenvariable, dh Sie sollten die Tabelle deklarieren. Dies ist keine temporäre Tabelle.

Sie erstellen eine temporäre Tabelle wie folgt:

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

Sie deklarieren eine Tabellenvariable wie folgt:

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

Beachten Sie, dass eine temporäre Tabelle mit # deklariert wird und eine Tabellenvariable mit einem @.Lesen Sie mehr über den Unterschied zwischen Tabellenvariablen und temporären Tabellen.

AKTUALISIERUNG:

Basierend auf Ihrem Kommentar unten versuchen Sie tatsächlich, Tabellen in einer gespeicherten Prozedur zu erstellen. Dazu müssten Sie dynamisches SQL verwenden. Grundsätzlich ermöglicht dynamisches SQL Ihnen, eine SQL-Anweisung in Form einer Zeichenfolge zu erstellen und diese dann auszuführen. Dies ist die EINZIGE Möglichkeit, eine Tabelle in einer gespeicherten Prozedur zu erstellen. Ich werde Ihnen zeigen, wie das geht, und dann diskutieren, warum dies im Allgemeinen keine gute Idee ist.

Nun zu einem einfachen Beispiel (ich habe diesen Code nicht getestet, aber er sollte Ihnen einen guten Hinweis darauf geben, wie es geht):

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

Diese gespeicherte Prozedur kann wie folgt ausgeführt werden:

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

Es gibt einige große Probleme mit dieser Art gespeicherter Prozeduren.

Es wird schwierig sein, komplexe Tabellen zu bedienen. Stellen Sie sich folgende Tabellenstruktur vor:

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 

Diese Tabelle ist etwas komplexer als das erste Beispiel, aber nicht viel. Die gespeicherte Prozedur wird viel, viel komplexer zu handhaben sein. Während dieser Ansatz also für kleine Tabellen funktionieren mag, wird er schnell unhandlich.

Das Erstellen von Tabellen erfordert Planung. Wenn Sie Tabellen erstellen, sollten diese strategisch in verschiedenen Dateigruppen platziert werden. Damit soll sichergestellt werden, dass Sie keine Festplatten-E/A-Konflikte verursachen. Wie gehen Sie mit der Skalierbarkeit um, wenn alles in der primären Dateigruppe erstellt wird?

Können Sie erläutern, warum Tabellen dynamisch erstellt werden müssen?

AKTUALISIERUNG 2:

Verzögertes Update aufgrund von Arbeitsbelastung. Ich habe Ihren Kommentar darüber gelesen, dass Sie für jeden Shop eine Tabelle erstellen müssen, und ich denke, Sie sollten es wie in dem Beispiel betrachten, das ich Ihnen gleich geben werde.

In diesem Beispiel gehe ich von folgenden Annahmen aus:

  1. Es ist eine E-Commerce-Website mit vielen Shops
  2. Ein Geschäft kann viele Artikel (Waren) zum Verkauf haben.
  3. Ein bestimmter Gegenstand (Ware) kann in vielen Geschäften verkauft werden
  4. Ein Geschäft berechnet unterschiedliche Preise für verschiedene Artikel (Waren)
  5. Alle Preise sind in $ (USD) angegeben

Angenommen, diese E-Commerce-Website verkauft Spielekonsolen (z. B. Wii, PS3, XBOX360).

Wenn ich meine Annahmen betrachte, sehe ich eine klassische Viele-zu-Viele-Beziehung. Ein Geschäft kann viele Gegenstände (Waren) verkaufen und Gegenstände (Waren) können in vielen Geschäften verkauft werden. Lassen Sie uns dies in Tabellen aufschlüsseln.

Zuerst bräuchte ich eine Shop-Tabelle, um alle Informationen über den Shop zu speichern.

Eine einfache Shop-Tabelle könnte so aussehen:

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

Lassen Sie uns drei Shops in die Datenbank einfügen, die in unserem Beispiel verwendet werden sollen. Der folgende Code fügt drei Shops ein:

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

Wenn Sie ein SELECT * FROM Shop ausführen Sie werden wahrscheinlich Folgendes sehen:

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

Richtig, also gehen wir jetzt zur Tabelle Artikel (Waren). Da es sich bei den Artikeln/Waren um Produkte verschiedener Unternehmen handelt, nenne ich das Tischprodukt. Sie können den folgenden Code ausführen, um eine einfache Produkttabelle zu erstellen.

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

Lassen Sie uns die Produkttabelle mit einigen Produkten füllen. Führen Sie den folgenden Code aus, um einige Produkte einzufügen:

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

Wenn Sie SELECT * FROM Product ausführen Sie werden wahrscheinlich Folgendes sehen:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, an dieser Stelle haben Sie sowohl Produkt- als auch Shop-Informationen. Wie bringt man sie zusammen? Nun, wir wissen, dass wir den Shop anhand seiner Primärschlüsselspalte ShopID identifizieren können, und wir wissen, dass wir ein Produkt anhand seiner Primärschlüsselspalte ProductID identifizieren können. Da außerdem jeder Shop einen anderen Preis für jedes Produkt hat, müssen wir den Preis speichern, den der Shop für das Produkt berechnet.

Wir haben also eine Tabelle, die den Shop dem Produkt zuordnet. Wir nennen diese Tabelle ShopProduct. Eine einfache Version dieser Tabelle könnte so aussehen:

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

Nehmen wir also an, der Shop von American Games R Us verkauft nur amerikanische Konsolen, die Europe Gaming Experience verkauft alle Konsolen und das Asian Games Emporium verkauft nur asiatische Konsolen. Wir müssten die Primärschlüssel aus den Shop- und Produkttabellen in die ShopProduct-Tabelle abbilden.

So werden wir das Mapping durchführen. In meinem Beispiel hat American Games R Us einen ShopID-Wert von 1 (dies ist der Primärschlüsselwert) und ich kann sehen, dass die XBOX360 einen Wert von 3 hat und der Shop die XBOX360 für 159,99 $ gelistet hat

Durch Ausführen des folgenden Codes würden Sie die Zuordnung abschließen:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Jetzt wollen wir alle Produkte zum Europe Gaming Experience Shop hinzufügen. In diesem Beispiel wissen wir, dass der Europe Gaming Experience-Shop eine ShopID von 3 hat, und da er alle Konsolen verkauft, müssen wir die ProductID 1, 2 und 3 in die Zuordnungstabelle einfügen. Nehmen wir an, die Preise für die Konsolen (Produkte) im Europe Gaming Experience Shop sind wie folgt:1- Die PS3 kostet 259,99 $ , 2- Die Wii kostet 159,99 $ , 3- Die XBOX360 kostet 199,99 $.

Um diese Zuordnung durchzuführen, müssten Sie den folgenden Code ausführen:

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

An dieser Stelle haben Sie zwei Shops und ihre Produkte in die Mapping-Tabelle gemappt. Okay, wie bringe ich das jetzt alles zusammen, um einem Benutzer zu zeigen, wie er auf der Website surft? Angenommen, Sie möchten einem Benutzer auf einer Webseite alle Produkte für das europäische Spielerlebnis zeigen – Sie müssten die folgende Abfrage ausführen:

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

Sie werden wahrscheinlich die folgenden Ergebnisse sehen:

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

Nehmen wir nun für ein letztes Beispiel an, dass Ihre Website über eine Funktion verfügt, die den günstigsten Preis für eine Konsole findet. Ein Benutzer fragt nach den günstigsten Preisen für XBOX360.

Sie können die folgende Abfrage ausführen:

 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

Diese Abfrage gibt eine Liste aller Shops zurück, die die XBOX360 zuerst mit dem günstigsten Shop verkaufen und so weiter.

Sie werden feststellen, dass ich den Shop für asiatische Spiele nicht hinzugefügt habe. Fügen Sie als Übung den Asian Games Shop mit den folgenden Produkten zur Mapping-Tabelle hinzu:Das Asian Games Emporium verkauft die Wii-Spielekonsole für 99,99 $ und die PS3-Konsole für 159,99 $. Wenn Sie dieses Beispiel durcharbeiten, sollten Sie nun verstehen, wie Sie eine Viele-zu-Viele-Beziehung modellieren.

Ich hoffe, das hilft Ihnen bei Ihren Reisen mit dem Datenbankdesign.