我已经基于通过存储过程传递的变量构建了一个动态查询。我的文字被评论为正在发生的事情。
首先,您需要一个表值函数来分割您的参数,以便其中列出的每个公司都是生成的返回表中的一行。这里是低于功能,你需要你的数据库上创建此:
CREATE FUNCTION [dbo].[ufnSplit]
(
@string VARCHAR(MAX),
@delimiter CHAR(1)
)
RETURNS @output TABLE(Item VARCHAR(MAX)
)
BEGIN
DECLARE @start INT, @end INT
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string)
WHILE @start < LEN(@string) + 1 BEGIN
IF @end = 0
SET @end = LEN(@string) + 1
INSERT INTO @output (Item)
VALUES(SUBSTRING(@string, @start, @end - @start))
SET @start = @end + 1
SET @end = CHARINDEX(@delimiter, @string, @start)
END
RETURN
END
接下来在存储过程中,我们使用此功能将参数分成数行,到一个临时表称为#Companies
。然后,我们使用一个循环来通过#Companies
来创建您的UNION
查询(或者,如果只有一个值)。再次,我已经对我正在做的事情做了很多评论。
USE [DatabaseName]
GO
CREATE PROCEDURE uspLevelReports
@param VARCHAR(MAX)
/* Use this for testing your parameters:
EXEC uspLevelReports @param = 'A,B,D'
*/
AS
BEGIN TRY
IF OBJECT_ID('tempdb..#Companies') IS NOT NULL
DROP TABLE #Companies
-- use the split function to put each company into a table, and assign it a row number (necessary for the loop below)
SELECT
Item
,ROW_NUMBER() OVER(ORDER BY Item ASC) AS RowNo
INTO #Companies
FROM dbo.ufnSplit(@param,',')
-- Select below is for testing so you can see the effect:
-- SELECT * FROM #Companies
-- Create the basic query here, with the company suffix
DECLARE @sql NVARCHAR(4000) = 'SELECT * From tempdb..##Level'
-- Start to loop through #Companies, for each row no higher than 1, a union will be added
-- First, tell the loop where to start and end:
DECLARE @RowNo INT = 1 -- Your starting RowNo, should always be 1 so won't do a MIN() here
DECLARE @MaxNo INT = (-- The highest RowNo in #Companies
SELECT
MAX(RowNo)
FROM #Companies
)
DECLARE @originalSQL NVARCHAR(4000) = @sql -- @Sql will be modified in the loop but we still need the original form to keep adding to each union if one is there
WHILE @RowNo <= @MaxNo -- we will increase the value of @RowNo by 1 each time,the loop will break when @RowNo gets higher than @MaxNo
BEGIN
-- Find the company that corresponds to the @RowNo value in #Companies and add it to a variable:
DECLARE @suffix VARCHAR(100) = (
SELECT
Item
FROM #Companies
WHERE RowNo = @RowNo)
IF @RowNo = @MaxNo -- If statement for the final Item in #Companies, this stops us adding UNION where we've finished the query
SET @sql += @suffix
ELSE
SET @sql += @suffix + ' UNION ' + @originalSQL;
SET @RowNo += 1 -- Add one to move to next RowNo in #Companies
PRINT @sql -- This is for testing so you can see in Messages how the query is being built each loop
END
PRINT 'Final query: ' + @sql -- This is for testing so you can see in Messages what your final query is
-- Create your level all table
IF OBJECT_ID('tempdb..##LevelAll') IS NOT NULL
DROP TABLE ##LevelAll
-- You need to create your ##LevelAll table with all the columns needed, so amend them with their datatypes below mine is just for example:
CREATE TABLE ##LevelAll(
Company CHAR(1)
,value INT
)
--- insert into your level all table
INSERT INTO ##LevelAll
-- by executing the statement inside your string variable
exec sp_executesql @sql
-- publish the results
SELECT * FROM ##LevelAll
END TRY
BEGIN CATCH
-- Your error trapping variables
END CATCH
来源
2016-12-01 16:28:13
TJB
公司与关卡有什么关系?不要告诉我你将每个公司的记录存储在一张单独的表格中!如果是这样,重新设计数据库。 –
您是否还在条件中创建临时表...如果您在存储过程开始时将它们声明为if ... – Hackerman
然后始终运行C级查询,以便永远不会失败。你可以填充任何东西('IF @doC然后SELECT ... INTO ... FROM; ELSE SELECT TOP(0)... INTO ... FROM;'或类似的方法来创建一个空表模式)。如果您可以通过使其他代码更复杂来避免动态查询,那么通常还是会付出代价的。然而,根据@Gordon,你可能会更好,因为预先设计的更好,所以这种查询不需要首先完成。 –