Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

T-SQL Comment créer dynamiquement des tables dans des procédures stockées ?

Vous utilisez une variable de table, c'est-à-dire que vous devez déclarer la table. Ceci n'est pas une table temporaire.

Vous créez une table temporaire comme suit :

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

Vous déclarez une variable de table comme suit :

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

Notez qu'une table temporaire est déclarée à l'aide de # et qu'une variable de table est déclarée à l'aide d'un @.Allez lire la différence entre les variables de table et les tables temporaires.

MISE À JOUR :

Sur la base de votre commentaire ci-dessous, vous essayez en fait de créer des tables dans une procédure stockée. Pour cela, vous devez utiliser SQL dynamique. Fondamentalement, le SQL dynamique vous permet de construire une instruction SQL sous la forme d'une chaîne, puis de l'exécuter. C'est le SEUL moyen de créer une table dans une procédure stockée. Je vais vous montrer comment et ensuite expliquer pourquoi ce n'est généralement pas une bonne idée.

Maintenant, pour un exemple simple (je n'ai pas testé ce code mais il devrait vous donner une bonne indication sur la façon de le faire) :

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

Cette procédure stockée peut être exécutée comme ceci :

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

Il y a quelques problèmes majeurs avec ce type de procédure stockée.

Il va être difficile de répondre aux tables complexes. Imaginez la structure de table suivante :

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 

Ce tableau est un peu plus complexe que le premier exemple, mais pas beaucoup. La procédure stockée sera beaucoup, beaucoup plus complexe à gérer. Ainsi, bien que cette approche puisse fonctionner pour les petites tables, elle deviendra rapidement ingérable.

La création de tableaux nécessite une planification. Lorsque vous créez des tables, elles doivent être placées stratégiquement sur différents groupes de fichiers. Cela permet de s'assurer que vous ne causez pas de conflit d'E/S disque. Comment allez-vous gérer l'évolutivité si tout est créé sur le groupe de fichiers principal ?

Pourriez-vous préciser pourquoi vous avez besoin que les tables soient créées dynamiquement ?

MISE À JOUR 2 :

Mise à jour retardée en raison de la charge de travail. J'ai lu votre commentaire sur la nécessité de créer un tableau pour chaque boutique et je pense que vous devriez envisager de le faire comme dans l'exemple que je suis sur le point de vous donner.

Dans cet exemple, je fais les hypothèses suivantes :

  1. C'est un site e-commerce qui compte de nombreuses boutiques
  2. Une boutique peut avoir de nombreux articles (marchandises) à vendre.
  3. Un article particulier (bien) peut être vendu dans de nombreux magasins
  4. Un magasin facturera des prix différents pour différents articles (marchandises)
  5. Tous les prix sont en $ (USD)

Disons que ce site de commerce électronique vend des consoles de jeu (c'est-à-dire Wii, PS3, XBOX360).

En regardant mes hypothèses, je vois une relation classique de plusieurs à plusieurs. Un magasin peut vendre de nombreux articles (marchandises) et des articles (marchandises) peuvent être vendus dans de nombreux magasins. Décomposons cela en tableaux.

J'aurais d'abord besoin d'une table de magasin pour stocker toutes les informations sur le magasin.

Une simple table de magasin pourrait ressembler à ceci :

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

Insérons trois boutiques dans la base de données à utiliser lors de notre exemple. Le code suivant insérera trois boutiques :

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

Si vous exécutez un SELECT * FROM Shop vous verrez probablement ce qui suit :

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

Bon, passons maintenant à la table des articles (marchandises). Étant donné que les articles/marchandises sont des produits de diverses entreprises, je vais appeler le produit de table. Vous pouvez exécuter le code suivant pour créer une simple table Product.

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

Remplissons la table des produits avec quelques produits. Exécutez le code suivant pour insérer des produits :

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

Si vous exécutez SELECT * FROM Product vous verrez probablement ce qui suit :

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

OK, à ce stade, vous avez à la fois des informations sur le produit et la boutique. Alors, comment les réunissez-vous ? Eh bien, nous savons que nous pouvons identifier la boutique par sa colonne de clé primaire ShopID et nous savons que nous pouvons identifier un produit par sa colonne de clé primaire ProductID. De plus, étant donné que chaque magasin a un prix différent pour chaque produit, nous devons stocker le prix que le magasin facture pour le produit.

Nous avons donc un tableau qui mappe la boutique au produit. Nous appellerons cette table ShopProduct. Une version simplifiée de ce tableau pourrait ressembler à ceci :

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

Supposons donc que la boutique American Games R Us ne vende que des consoles américaines, que l'Europe Gaming Experience vend toutes les consoles et que l'Asian Games Emporium ne vend que des consoles asiatiques. Nous aurions besoin de mapper les clés primaires des tables de boutique et de produit dans la table ShopProduct.

Voici comment nous allons faire la cartographie. Dans mon exemple, American Games R Us a une valeur ShopID de 1 (il s'agit de la valeur de la clé primaire) et je peux voir que la XBOX360 a une valeur de 3 et que la boutique a répertorié la XBOX360 pour 159,99 $

En exécutant le code suivant, vous terminerez le mappage :

INSERT INTO ShopProduct VALUES(1,3,159.99)

Maintenant, nous voulons ajouter tous les produits à la boutique Europe Gaming Experience. Dans cet exemple, nous savons que la boutique Europe Gaming Experience a un ShopID de 3 et puisqu'elle vend toutes les consoles, nous devrons insérer les ProductID 1, 2 et 3 dans la table de mappage. Supposons que les prix des consoles (produits) dans la boutique Europe Gaming Experience sont les suivants :1- La PS3 se vend 259,99 $ , 2- La Wii se vend 159,99 $ , 3- La XBOX360 se vend 199,99 $.

Pour effectuer ce mappage, vous devez exécuter le code suivant :

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

À ce stade, vous avez mappé deux magasins et leurs produits dans la table de mappage. OK, alors maintenant, comment puis-je rassembler tout cela pour montrer à un utilisateur naviguant sur le site ? Supposons que vous souhaitiez montrer tous les produits de l'expérience de jeu européenne à un utilisateur sur une page Web. Vous devrez exécuter la requête suivante :

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

Vous verrez probablement les résultats suivants :

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

Maintenant, pour un dernier exemple, supposons que votre site Web dispose d'une fonctionnalité qui trouve le prix le moins cher pour une console. Un utilisateur demande à trouver les prix les moins chers pour XBOX360.

Vous pouvez exécuter la requête suivante :

 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

Cette requête renverra une liste de tous les magasins qui vendent la XBOX360 avec le magasin le moins cher en premier et ainsi de suite.

Vous remarquerez que je n'ai pas ajouté la boutique Asian Games. À titre d'exercice, ajoutez la boutique de jeux asiatiques au tableau de mappage avec les produits suivants :l'Asian Games Emporium vend la console de jeux Wii pour 99,99 $ et la console PS3 pour 159,99 $. Si vous travaillez sur cet exemple, vous devriez maintenant comprendre comment modéliser une relation plusieurs-à-plusieurs.

J'espère que cela vous aidera dans vos déplacements avec la conception de bases de données.