Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

T-SQL Как да създавам динамично таблици в съхранени процедури?

Вие използвате променлива на таблица, т.е. трябва да декларирате таблицата. Това не е временна таблица.

Създавате временна таблица така:

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

Вие декларирате променлива на таблицата така:

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

Забележете, че временна таблица се декларира с помощта на #, а таблична променлива се декларира с @.Go прочетете за разликата между променливите на таблицата и временните таблици.

АКТУАЛИЗИРАНЕ:

Въз основа на вашия коментар по-долу вие всъщност се опитвате да създадете таблици в съхранена процедура. За това ще трябва да използвате динамичен SQL. По принцип динамичният SQL ви позволява да конструирате SQL изявление под формата на низ и след това да го изпълните. Това е ЕДИНСТВЕНИЯТ начин, по който ще можете да създадете таблица в съхранена процедура. Ще ви покажа как и след това ще обсъдя защо това обикновено не е добра идея.

Сега за един прост пример (не съм тествал този код, но трябва да ви даде добра индикация как да го направите):

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

Тази съхранена процедура може да се изпълни по следния начин:

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

Има някои големи проблеми с този тип съхранени процедури.

Ще бъде трудно да се погрижи за сложни маси. Представете си следната структура на таблицата:

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 

Тази таблица е малко по-сложна от първия пример, но не много. Съхранената процедура ще бъде много, много по-сложна за справяне. Така че, докато този подход може да работи за малки таблици, той бързо ще бъде неуправляем.

Създаването на таблици изисква планиране. Когато създавате таблици, те трябва да бъдат поставени стратегически в различни файлови групи. Това е, за да се гарантира, че няма да предизвикате спорове за дисков I/O. Как ще се справите с мащабируемостта, ако всичко е създадено в основната файлова група?

Бихте ли пояснили защо имате нужда от динамично създаване на таблици?

АКТУАЛИЗАЦИЯ 2:

Забавена актуализация поради натоварване. Прочетох коментара ви относно необходимостта от създаване на таблица за всеки магазин и мисля, че трябва да гледате на това като примера, който ще ви дам.

В този пример правя следните предположения:

  1. Това е сайт за електронна търговия, който има много магазини
  2. Един магазин може да има много артикули (стоки) за продажба.
  3. Конкретен артикул (стока) може да се продава в много магазини
  4. Един магазин ще таксува различни цени за различните артикули (стоки)
  5. Всички цени са в $ (USD)

Да кажем, че този сайт за електронна търговия продава игрови конзоли (напр. Wii, PS3, XBOX360).

Разглеждайки моите предположения, виждам класическа връзка много към много. Един магазин може да продава много артикули (стоки) и артикули (стоки) могат да се продават в много магазини. Нека да разделим това на таблици.

Първо ще ми трябва магазинна таблица, за да съхранявам цялата информация за магазина.

Една проста маса за магазин може да изглежда така:

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

Нека вмъкнем три магазина в базата данни, които да използваме по време на нашия пример. Следният код ще вмъкне три магазина:

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

Ако изпълните SELECT * FROM Shop вероятно ще видите следното:

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

Добре, така че сега нека преминем към таблицата с артикули (стоки). Тъй като артикулите/стоките са продукти на различни компании, ще нарека таблица продукт. Можете да изпълните следния код, за да създадете проста таблица с продукти.

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

Нека попълним таблицата с продукти с някои продукти. Изпълнете следния код, за да вмъкнете някои продукти:

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

Ако изпълните SELECT * FROM Product вероятно ще видите следното:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

Добре, в този момент имате информация както за продукта, така и за магазина. И така, как да ги съберете заедно? Е, ние знаем, че можем да идентифицираме магазина по неговата колона с първичен ключ ShopID и знаем, че можем да идентифицираме продукт по неговата колона с първичен ключ на ProductID. Освен това, тъй като всеки магазин има различна цена за всеки продукт, ние трябва да съхраняваме цената, която магазинът начислява за продукта.

Така че имаме таблица, която съпоставя Магазина с продукта. Ще наречем тази таблица ShopProduct. Една проста версия на тази таблица може да изглежда така:

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

Така че нека приемем, че магазинът на American Games R Us продава само американски конзоли, Europe Gaming Experience продава всички конзоли, а Asian Games Emporium продава само азиатски конзоли. Ще трябва да съпоставим първичните ключове от таблиците магазин и продукти в таблицата ShopProduct.

Ето как ще направим картографирането. В моя пример American Games R Us има стойност на ShopID от 1 (това е стойността на първичния ключ) и виждам, че XBOX360 има стойност 3 и магазинът е посочил XBOX360 за $159,99

Чрез изпълнение на следния код ще завършите съпоставянето:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Сега искаме да добавим всички продукти към магазина Europe Gaming Experience. В този пример знаем, че магазинът Europe Gaming Experience има ShopID от 3 и тъй като той продава всички конзоли, ще трябва да вмъкнем ProductID 1, 2 и 3 в таблицата за съпоставяне. Да приемем, че цените на конзолите (продуктите) в магазина Europe Gaming Experience са следните:1- PS3 се продава за $259,99, 2- Wii се продава за $159,99, 3- XBOX360 се продава за $199,99.

За да извършите това картографиране, ще трябва да изпълните следния код:

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

В този момент сте картографирали два магазина и техните продукти в таблицата за картографиране. Добре, сега как да събера всичко това, за да покажа потребител, който разглежда уебсайта? Да приемем, че искате да покажете целия продукт за европейското игрово изживяване на потребител на уеб страница – ще трябва да изпълните следната заявка:

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

Вероятно ще видите следните резултати:

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

Сега за последен пример, нека предположим, че вашият уебсайт има функция, която намира най-евтината цена за конзола. Потребител иска да намери най-евтините цени за XBOX360.

Можете да изпълните следната заявка:

 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

Тази заявка ще върне списък с всички магазини, които продават XBOX360 първо с най-евтиния магазин и така нататък.

Ще забележите, че не съм добавил магазина на Азиатските игри. Като упражнение добавете магазина за азиатски игри към таблицата за картографиране със следните продукти:Asian Games Emporium продава игровата конзола Wii за $99,99 и PS3 конзолата за $159,99. Ако работите с този пример, сега трябва да разберете как да моделирате връзка много към много.

Надявам се това да ви помогне в пътуванията ви с дизайна на база данни.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Лесното ръководство за това как да използвате подзаявки в SQL Server

  2. SQL Server 2008 празен низ срещу пространство

  3. Как да инсталирате SQL Server на Mac

  4. Създайте база данни на SQL Server с SQLOPS

  5. Примери за SQL Server ЗА JSON ПЪТ (T-SQL)