sql >> Base de Datos >  >> RDS >> Sqlserver

T-SQL ¿Cómo crear tablas dinámicamente en procedimientos almacenados?

Está utilizando una variable de tabla, es decir, debe declarar la tabla. Esta no es una tabla temporal.

Creas una tabla temporal así:

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

Declaras una variable de tabla así:

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

Tenga en cuenta que una tabla temporal se declara con # y una variable de tabla se declara con @. Vaya a leer acerca de la diferencia entre las variables de tabla y las tablas temporales.

ACTUALIZACIÓN:

Según su comentario a continuación, en realidad está intentando crear tablas en un procedimiento almacenado. Para esto, necesitaría usar SQL dinámico. Básicamente, el SQL dinámico le permite construir una instrucción SQL en forma de cadena y luego ejecutarla. Esta es la ÚNICA forma en que podrá crear una tabla en un procedimiento almacenado. Le mostraré cómo hacerlo y luego explicaré por qué no suele ser una buena idea.

Ahora, un ejemplo simple (no he probado este código, pero debería darle una buena indicación de cómo hacerlo):

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

Este procedimiento almacenado se puede ejecutar así:

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

Hay algunos problemas importantes con este tipo de procedimiento almacenado.

Va a ser difícil atender mesas complejas. Imagine la siguiente estructura de tabla:

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 

Esta tabla es un poco más compleja que el primer ejemplo, pero no mucho. El procedimiento almacenado será mucho, mucho más complejo de manejar. Entonces, si bien este enfoque podría funcionar para tablas pequeñas, pronto se volverá inmanejable.

La creación de tablas requiere planificación. Cuando crea tablas, deben colocarse estratégicamente en diferentes grupos de archivos. Esto es para garantizar que no provoque contención de E/S de disco. ¿Cómo abordará la escalabilidad si todo se crea en el grupo de archivos principal?

¿Podría aclarar por qué necesita que las tablas se creen dinámicamente?

ACTUALIZACIÓN 2:

Actualización retrasada debido a la carga de trabajo. Leí su comentario sobre la necesidad de crear una tabla para cada tienda y creo que debería considerar hacerlo como el ejemplo que estoy a punto de darle.

En este ejemplo hago las siguientes suposiciones:

  1. Es un sitio de comercio electrónico que tiene muchas tiendas
  2. Una tienda puede tener muchos artículos (bienes) para vender.
  3. Un artículo en particular (bien) se puede vender en muchas tiendas
  4. Una tienda cobrará diferentes precios por diferentes artículos (bienes)
  5. Todos los precios están en $ (USD)

Digamos que este sitio de comercio electrónico vende consolas de juegos (es decir, Wii, PS3, XBOX360).

Mirando mis suposiciones, veo una relación clásica de muchos a muchos. Una tienda puede vender muchos artículos (mercancías) y los artículos (mercancías) se pueden vender en muchas tiendas. Vamos a dividir esto en tablas.

Primero necesitaría una tabla de tienda para almacenar toda la información sobre la tienda.

Una mesa de compras simple podría verse así:

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

Insertemos tres tiendas en la base de datos para usar durante nuestro ejemplo. El siguiente código insertará tres tiendas:

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

Si ejecuta un SELECT * FROM Shop probablemente verá lo siguiente:

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

Correcto, ahora pasemos a la tabla Artículos (mercancías). Dado que los artículos/mercancías son productos de varias empresas, voy a llamar a la tabla producto. Puede ejecutar el siguiente código para crear una tabla de productos simple.

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

Completemos la tabla de productos con algunos productos. Ejecute el siguiente código para insertar algunos productos:

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

Si ejecuta SELECT * FROM Product probablemente verá lo siguiente:

ProductID   ProductDescription
1           PS3
2           Wii
3           XBOX360

Bien, en este punto tiene información tanto del producto como de la tienda. Entonces, ¿cómo los unes? Bueno, sabemos que podemos identificar la tienda por su columna de clave principal ShopID y sabemos que podemos identificar un producto por su columna de clave principal ProductID. Además, dado que cada tienda tiene un precio diferente para cada producto, necesitamos almacenar el precio que la tienda cobra por el producto.

Entonces tenemos una tabla que mapea la Tienda al producto. Llamaremos a esta tabla ShopProduct. Una versión simple de esta tabla podría verse así:

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

Entonces, supongamos que la tienda American Games R Us solo vende consolas estadounidenses, Europe Gaming Experience vende todas las consolas y Asian Games Emporium vende solo consolas asiáticas. Tendríamos que asignar las claves principales de las tablas de productos y tiendas a la tabla ShopProduct.

Así es como vamos a hacer el mapeo. En mi ejemplo, American Games R Us tiene un valor ShopID de 1 (este es el valor de la clave principal) y puedo ver que XBOX360 tiene un valor de 3 y la tienda ha incluido XBOX360 por $ 159.99

Al ejecutar el siguiente código, completaría el mapeo:

INSERT INTO ShopProduct VALUES(1,3,159.99)

Ahora queremos agregar todos los productos a la tienda Europe Gaming Experience. En este ejemplo, sabemos que la tienda Europe Gaming Experience tiene un ShopID de 3 y dado que vende todas las consolas, necesitaremos insertar el ProductID 1, 2 y 3 en la tabla de mapeo. Supongamos que los precios de las consolas (productos) en la tienda Europe Gaming Experience son los siguientes:1- La PS3 se vende a $259,99 , 2- La Wii se vende a $159,99 , 3- La XBOX360 se vende a $199,99.

Para realizar esta asignación, deberá ejecutar el siguiente código:

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

En este punto, ha mapeado dos tiendas y sus productos en la tabla de mapeo. Bien, ahora, ¿cómo reúno todo esto para mostrar a un usuario navegando por el sitio web? Supongamos que desea mostrar todo el producto para la experiencia de juego europea a un usuario en una página web; deberá ejecutar la siguiente consulta:

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

Probablemente verá los siguientes resultados:

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

Ahora, para un último ejemplo, supongamos que su sitio web tiene una función que encuentra el precio más barato para una consola. Un usuario pide encontrar los precios más baratos para XBOX360.

Puede ejecutar la siguiente consulta:

 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

Esta consulta devolverá una lista de todas las tiendas que venden la XBOX360 con la tienda más barata primero y así sucesivamente.

Notarás que no he agregado la tienda de los Juegos Asiáticos. Como ejercicio, agregue la tienda de juegos asiáticos a la tabla de mapeo con los siguientes productos:Asian Games Emporium vende la consola de juegos Wii por $99.99 y la consola PS3 por $159.99. Si trabaja con este ejemplo, ahora debería comprender cómo modelar una relación de muchos a muchos.

Espero que esto te ayude en tus viajes con el diseño de la base de datos.