Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

T-SQL Jak dynamicznie tworzyć tabele w procedurach składowanych?

Używasz zmiennej tabeli, tzn. powinieneś zadeklarować tabelę. To nie jest tabela tymczasowa.

Tworzysz tabelę tymczasową w następujący sposób:

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

Deklarujesz zmienną tabeli w następujący sposób:

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

Zauważ, że tabela temp jest zadeklarowana za pomocą #, a zmienna tabeli jest zadeklarowana za pomocą @.Go przeczytaj o różnicy między zmiennymi tabel a tabelami tymczasowymi.

AKTUALIZACJA:

Na podstawie poniższego komentarza faktycznie próbujesz utworzyć tabele w procedurze składowanej. W tym celu musisz użyć dynamicznego SQL. Zasadniczo dynamiczny SQL umożliwia skonstruowanie instrukcji SQL w postaci ciągu, a następnie jej wykonanie. Jest to JEDYNY sposób tworzenia tabeli w procedurze składowanej. Pokażę ci, jak, a następnie przedyskutuję, dlaczego generalnie nie jest to dobry pomysł.

Teraz prosty przykład (nie testowałem tego kodu, ale powinien dać ci dobrą wskazówkę, jak to zrobić):

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

Tę procedurę składowaną można wykonać w następujący sposób:

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

Istnieje kilka poważnych problemów związanych z tego typu procedurą składowaną.

Trudno będzie obsłużyć złożone stoły. Wyobraź sobie następującą strukturę tabeli:

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 

Ta tabela jest nieco bardziej złożona niż pierwszy przykład, ale niewiele. Procedura składowana będzie o wiele bardziej skomplikowana. Więc chociaż to podejście może działać w przypadku małych tabel, szybko będzie niemożliwe do zarządzania.

Tworzenie tabel wymaga planowania. Podczas tworzenia tabel należy je strategicznie umieszczać w różnych grupach plików. Ma to na celu zapewnienie, że nie spowodujesz rywalizacji we/wy dysku. Jak zajmiesz się skalowalnością, jeśli wszystko jest tworzone w podstawowej grupie plików?

Czy możesz wyjaśnić, dlaczego tabele muszą być tworzone dynamicznie?

AKTUALIZACJA 2:

Opóźniona aktualizacja z powodu obciążenia pracą. Przeczytałem Twój komentarz o potrzebie stworzenia stołu dla każdego sklepu i myślę, że powinieneś spojrzeć na to, jak na przykład, który ci podam.

W tym przykładzie przyjmuję następujące założenia:

  1. To witryna e-commerce, która ma wiele sklepów
  2. Sklep może mieć wiele przedmiotów (towarów) do sprzedania.
  3. Określony przedmiot (dobry) można sprzedawać w wielu sklepach
  4. Sklep będzie naliczał różne ceny za różne przedmioty (towary)
  5. Wszystkie ceny są podane w USD (USD)

Załóżmy, że ta witryna e-commerce sprzedaje konsole do gier (tj. Wii, PS3, XBOX360).

Patrząc na moje założenia, widzę klasyczną relację wiele do wielu. Sklep może sprzedawać wiele przedmiotów (towarów), a przedmioty (towary) można sprzedawać w wielu sklepach. Podzielmy to na tabele.

Najpierw potrzebuję tabeli sklepowej, aby przechowywać wszystkie informacje o sklepie.

Prosty stół sklepowy może wyglądać tak:

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

Wstawmy trzy sklepy do bazy danych do wykorzystania w naszym przykładzie. Poniższy kod wstawi trzy sklepy:

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

Jeśli wykonasz SELECT * FROM Shop prawdopodobnie zobaczysz:

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

Tak, przejdźmy teraz do tabeli Pozycje (towary). Ponieważ przedmioty/towary są produktami różnych firm, będę nazywał produkt stołowy. Możesz wykonać następujący kod, aby utworzyć prostą tabelę produktów.

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

Wypełnijmy tabelę produktów niektórymi produktami. Wykonaj następujący kod, aby wstawić niektóre produkty:

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

Jeśli wykonasz SELECT * FROM Product prawdopodobnie zobaczysz:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, w tym momencie masz zarówno informacje o produkcie, jak i sklepie. Więc jak je łączysz? Dobrze wiemy, że możemy zidentyfikować sklep za pomocą kolumny klucza podstawowego ShopID i wiemy, że możemy zidentyfikować produkt za pomocą kolumny klucza podstawowego ProductID. Ponadto, ponieważ każdy sklep ma inną cenę za każdy produkt, musimy przechowywać cenę, którą sklep pobiera za produkt.

Mamy więc tabelę, która mapuje Sklep do produktu. Nazwiemy tę tabelę ShopProduct. Prosta wersja tej tabeli może wyglądać tak:

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

Załóżmy więc, że sklep American Games R Us sprzedaje wyłącznie konsole amerykańskie, Europe Gaming Experience sprzedaje wszystkie konsole, a Asian Games Emporium sprzedaje wyłącznie konsole azjatyckie. Musielibyśmy zmapować klucze podstawowe ze sklepu i tabel produktów do tabeli ShopProduct.

Oto jak zrobimy mapowanie. W moim przykładzie American Games R Us ma wartość ShopID równą 1 (jest to wartość klucza podstawowego) i widzę, że XBOX360 ma wartość 3, a sklep wystawił XBOX360 za 159,99 USD

Wykonując następujący kod, zakończysz mapowanie:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Teraz chcemy dodać wszystkie produkty do sklepu Europe Gaming Experience. W tym przykładzie wiemy, że sklep Europe Gaming Experience ma ShopID równy 3, a ponieważ sprzedaje wszystkie konsole, będziemy musieli wstawić ProductID 1, 2 i 3 do tabeli mapowania. Załóżmy, że ceny konsol (produktów) w sklepie Europe Gaming Experience są następujące:1- PS3 kosztuje 259,99 $, 2- Wii kosztuje 159,99 $, 3- XBOX360 kosztuje 199,99 $.

Aby wykonać to mapowanie, musisz wykonać następujący 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

W tym momencie zmapowałeś dwa sklepy i ich produkty do tabeli mapowania. OK, więc teraz, jak mam to wszystko zebrać, aby pokazać użytkownikowi przeglądającemu witrynę? Załóżmy, że chcesz pokazać użytkownikowi całą usługę European Gaming Experience na stronie internetowej — musisz wykonać następujące zapytanie:

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

Prawdopodobnie zobaczysz następujące wyniki:

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

A teraz ostatni przykład, załóżmy, że Twoja witryna ma funkcję, która znajduje najtańszą cenę za konsolę. Użytkownik prosi o znalezienie najtańszych cen na XBOX360.

Możesz wykonać następujące zapytanie:

 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

To zapytanie zwróci listę wszystkich sklepów, które sprzedają XBOX360 z najtańszym sklepem jako pierwszym i tak dalej.

Zauważysz, że nie dodałem sklepu Asian Games. W ramach ćwiczenia dodaj sklep z grami azjatyckimi do tabeli mapowania z następującymi produktami:Asian Games Emporium sprzedaje konsolę do gier Wii za 99,99 USD, a konsolę PS3 za 159,99 USD. Jeśli zapoznasz się z tym przykładem, powinieneś zrozumieć, jak modelować relację wiele do wielu.

Mam nadzieję, że pomoże to w podróżach z projektowaniem baz danych.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jakie jest zastosowanie GO w SQL Server Management Studio i Transact SQL?

  2. Zmień format daty dla bieżącej sesji w SQL Server

  3. Dynamiczne maskowanie danych w SQL Server dla zaawansowanych użytkowników

  4. Jak zwrócić listę typów danych w SQL Server (T-SQL)

  5. SELECT INTO zmienną tabeli w T-SQL