select 的存储过程逻辑
Stored procedure logic for select
我有以下程序:
CREATE PROCEDURE sp_types
@type varchar(100)
AS
BEGIN
DECLARE @products table(productId int)
IF @type = 'Merchandise'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE IF @type = 'Electronics'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE IF @type = 'Home'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
/* here we have logic to convert all the productids in the @products table into an XML format
<products>
<productId>1</productId>
<productId>2</productId>
....
....
....
<productId>100</productId>
</products>
*/
/* after we get the XML string, it is passed to another procedure to print out details about the products */
EXEC sp_products_list @xml = @productXml
END /* procedure ends here */
这是 sp_products_list
程序:
CREATE PROCEDURE sp_products_list
@xml XML
AS
BEGIN
DECLARE @products TABLE (productId int)
INSERT INTO @products
SELECT @xml.value('productId','int')
FROM @xml.nodes('products')
/* Select statement */
SELECT
a.productId, a.productName,
b.productRegion, b.ProductQuantity,
c.productSupplier
FROM
products a
JOIN
productRegion b ON a.productid = b.productid
JOIN
productSupplier c ON c.productRegion = b.productRegion
WHERE
a.productId IN (SELECT productId FROM @products)
END /* procedure end */
sp_products_list
被 sp_types
过程以外的许多其他过程调用。我有一个要求,当我将 'Merchandise' 类型传递给 sp_types
过程时,我需要显示一些额外的列,如 productSupplierRegion
、productSupplierCount
等。
但对于其余类型,我只需要显示 sp_products_list
过程中的 select 语句当前显示的内容即可。
如果我只是将我需要的列添加到当前 sp_products_list
过程中的 select 语句中,那么它们将针对传递给 sp_types
过程的任何类型显示这不是我想要的。
我的解决方案:我能想到的解决方案之一是在 sp_products_list
过程中接收一个 @type 变量作为输入,并为 select 语句设置一个 if-else 语句。如果传入 'Merchandise' 类型,则显示带有附加列的 select 否则显示常规列。
我将来使用这种方法可能面临的问题是,如果我们想为传入的不同 @type
变量添加不同类型的列怎么办。在那种情况下,我将不得不为每种类型执行多个 if-else 语句。我原计划使用动态 SQL 但我的想法被否决了,因为我的团队不是动态 SQL.
的忠实粉丝
现在我正在尝试为这个问题找到一个可能适用于任何情况的可靠解决方案。有什么想法或建议吗?谢谢!
我建议您将 sp_products_list
重写为 table 值函数,然后您可以将它与您需要的任何额外列连接起来
CREATE OR ALTER FUNCTION dbo.products_list ( @productId int )
RETURNS TABLE
AS RETURN
SELECT
p.productId, p.productName,
pr.productRegion, pr.ProductQuantity,
ps.productSupplier
FROM
products p
JOIN
productRegion pr ON p.productid = pr.productid
JOIN
productSupplier ps ON ps.productRegion = pr.productRegion
WHERE
p.productId = @productId;
GO
然后您只需在每个过程中使用该函数即可。例如。
CREATE PROCEDURE ProductByType
@type varchar(100)
AS
IF @type = 'Merchandise'
BEGIN
SELECT pl.*, p.OtherColumns, t.OtherTablesColumns
FROM dbo.product p
CROSS APPLY dbo.products_list (p.productId) pl
LEFT JOIN OtherTable t ON SomeCondition
WHERE p.type = @type;
END;
ELSE
BEGIN
SELECT pl.*
FROM dbo.product p
CROSS APPLY dbo.products_list (p.productId) pl
WHERE p.type = @type;
END;
您可能会发现将 @type
选择也推入函数会更高效。然后你可以简单地做
SELECT pl.*
FROM dbo.products_list_by_type (@type) pl
服务器将从查询计划中删除任何不需要的列。
我有以下程序:
CREATE PROCEDURE sp_types
@type varchar(100)
AS
BEGIN
DECLARE @products table(productId int)
IF @type = 'Merchandise'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE IF @type = 'Electronics'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE IF @type = 'Home'
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
ELSE
BEGIN
INSERT INTO @products
SELECT productId
FROM dbo.product
WHERE type = @type
END
/* here we have logic to convert all the productids in the @products table into an XML format
<products>
<productId>1</productId>
<productId>2</productId>
....
....
....
<productId>100</productId>
</products>
*/
/* after we get the XML string, it is passed to another procedure to print out details about the products */
EXEC sp_products_list @xml = @productXml
END /* procedure ends here */
这是 sp_products_list
程序:
CREATE PROCEDURE sp_products_list
@xml XML
AS
BEGIN
DECLARE @products TABLE (productId int)
INSERT INTO @products
SELECT @xml.value('productId','int')
FROM @xml.nodes('products')
/* Select statement */
SELECT
a.productId, a.productName,
b.productRegion, b.ProductQuantity,
c.productSupplier
FROM
products a
JOIN
productRegion b ON a.productid = b.productid
JOIN
productSupplier c ON c.productRegion = b.productRegion
WHERE
a.productId IN (SELECT productId FROM @products)
END /* procedure end */
sp_products_list
被 sp_types
过程以外的许多其他过程调用。我有一个要求,当我将 'Merchandise' 类型传递给 sp_types
过程时,我需要显示一些额外的列,如 productSupplierRegion
、productSupplierCount
等。
但对于其余类型,我只需要显示 sp_products_list
过程中的 select 语句当前显示的内容即可。
如果我只是将我需要的列添加到当前 sp_products_list
过程中的 select 语句中,那么它们将针对传递给 sp_types
过程的任何类型显示这不是我想要的。
我的解决方案:我能想到的解决方案之一是在 sp_products_list
过程中接收一个 @type 变量作为输入,并为 select 语句设置一个 if-else 语句。如果传入 'Merchandise' 类型,则显示带有附加列的 select 否则显示常规列。
我将来使用这种方法可能面临的问题是,如果我们想为传入的不同 @type
变量添加不同类型的列怎么办。在那种情况下,我将不得不为每种类型执行多个 if-else 语句。我原计划使用动态 SQL 但我的想法被否决了,因为我的团队不是动态 SQL.
现在我正在尝试为这个问题找到一个可能适用于任何情况的可靠解决方案。有什么想法或建议吗?谢谢!
我建议您将 sp_products_list
重写为 table 值函数,然后您可以将它与您需要的任何额外列连接起来
CREATE OR ALTER FUNCTION dbo.products_list ( @productId int )
RETURNS TABLE
AS RETURN
SELECT
p.productId, p.productName,
pr.productRegion, pr.ProductQuantity,
ps.productSupplier
FROM
products p
JOIN
productRegion pr ON p.productid = pr.productid
JOIN
productSupplier ps ON ps.productRegion = pr.productRegion
WHERE
p.productId = @productId;
GO
然后您只需在每个过程中使用该函数即可。例如。
CREATE PROCEDURE ProductByType
@type varchar(100)
AS
IF @type = 'Merchandise'
BEGIN
SELECT pl.*, p.OtherColumns, t.OtherTablesColumns
FROM dbo.product p
CROSS APPLY dbo.products_list (p.productId) pl
LEFT JOIN OtherTable t ON SomeCondition
WHERE p.type = @type;
END;
ELSE
BEGIN
SELECT pl.*
FROM dbo.product p
CROSS APPLY dbo.products_list (p.productId) pl
WHERE p.type = @type;
END;
您可能会发现将 @type
选择也推入函数会更高效。然后你可以简单地做
SELECT pl.*
FROM dbo.products_list_by_type (@type) pl
服务器将从查询计划中删除任何不需要的列。