Stored procedures SQL Server中的多列动态排序

Stored procedures SQL Server中的多列动态排序,stored-procedures,sql-server-2012,sql-order-by,Stored Procedures,Sql Server 2012,Sql Order By,我使用SQL Server 2012。我有一个名为“Table1”的示例表,它有七列 CREATE TABLE TABLE1 ( Field1 INT , Field2 INT , Field3 INT , Field4 INT , Field5 INT ,

我使用SQL Server 2012。我有一个名为“Table1”的示例表,它有七列

        CREATE TABLE TABLE1 
            (
                Field1 INT , 
                Field2 INT , 
                Field3 INT , 
                Field4 INT , 
                Field5 INT , 
                Field6 INT , 
                Field7 INT 
            )
            GO

        INSERT INTO TABLE1 VALUES (1,2,9,5,1,5,85)
        INSERT INTO TABLE1 VALUES (2,6,8,4,1,4,45)
        INSERT INTO TABLE1 VALUES (3,5,7,3,5,6,1)
        INSERT INTO TABLE1 VALUES (4,4,6,1,51,4,1)
        INSERT INTO TABLE1 VALUES (5,5,5,4,7,2,7)
        INSERT INTO TABLE1 VALUES (6,5,4,6,4,7,8)
        INSERT INTO TABLE1 VALUES (7,12,5,3,2,5,3)
        INSERT INTO TABLE1 VALUES (8,1,6,5,9,5,1)
        INSERT INTO TABLE1 VALUES (9,1,13,2,1,7,3)
        INSERT INTO TABLE1 VALUES (10,6,9,3,6,2,6)
        INSERT INTO TABLE1 VALUES (11,2,1,2,8,7,7)
        INSERT INTO TABLE1 VALUES (12,7,6,1,3,3,2)
        INSERT INTO TABLE1 VALUES (13,7,2,6,4,7,1)
        GO
我已经创建了以下存储过程,该SP能够根据列的顺序查询数据。 我可以通过(ASC或Desc)查询每种可能的单列和排序方式的表

现在,我需要更改此sp,以便将多列作为按系列排序的列接受。它们可以按名称传递,也可以按列的顺序传递。 在这种情况下,我应该能够像下面的命令一样执行SP:

    EXECUTE ProceName  @OrderByField='6,7,2', @OrderDirection='0,1,1'

如何在不使用sp_executesql(动态查询)的情况下实现这一目标?

好吧,除非您尝试为每列选择asc和desc,否则升序和降序在您的情况下并不重要。这里使用的是最后一列

DECLARE @OrderByField VARCHAR(64) = '1,3,7'

DECLARE @DynamicColumns VARCHAR(256) = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@OrderByField,1,'FIELD1'),2,'FIELD2'),3,'FIELD3'),4,'FIELD4'),5,'FIELD5'),6,'FIELD6'),7,'FIELD7')

DECLARE @OrderDirection INT = 1
DECLARE @order varchar(4)
SET @order = CASE WHEN @OrderDirection = 1 THEN 'DESC' ELSE 'ASC' END

--uncomment this line of code to add the sort to every column which only matters for DESC since ASC is default
--SET @DynamicColumns = REPLACE(@DynamicColumns,',', ' ' + @order + ',')

DECLARE @sql VARCHAR(MAX) = (
        'SELECT
                *  
        FROM Table1
        ORDER BY ' + @DynamicColumns + ' ' + @order)

SELECT @sql

EXEC(@sql)

嗯,在您的情况下,升序和降序并不重要,除非您尝试为每个列选择asc和desc。这里使用的是最后一列

DECLARE @OrderByField VARCHAR(64) = '1,3,7'

DECLARE @DynamicColumns VARCHAR(256) = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@OrderByField,1,'FIELD1'),2,'FIELD2'),3,'FIELD3'),4,'FIELD4'),5,'FIELD5'),6,'FIELD6'),7,'FIELD7')

DECLARE @OrderDirection INT = 1
DECLARE @order varchar(4)
SET @order = CASE WHEN @OrderDirection = 1 THEN 'DESC' ELSE 'ASC' END

--uncomment this line of code to add the sort to every column which only matters for DESC since ASC is default
--SET @DynamicColumns = REPLACE(@DynamicColumns,',', ' ' + @order + ',')

DECLARE @sql VARCHAR(MAX) = (
        'SELECT
                *  
        FROM Table1
        ORDER BY ' + @DynamicColumns + ' ' + @order)

SELECT @sql

EXEC(@sql)

我认为op试图实现的是为每个项目指定顺序columnfield@LONG那么就必须有更多的参数,每列一个……是的。。。这将是复杂的,即使是简单的输入。我认为op试图实现的是为每个输入指定顺序columnfield@LONG那么就必须有更多的参数,每列一个……是的。。。即使是简单的输入,这也会很复杂。逻辑是创建两个表来存储两个输入数据,使用
CHARINDEX
存储每个输入的每个元素;从连接的结果中选择数据,使用表游标生成每一对,然后使用动态sql获得最终结果我一直在寻找不使用动态查询的方法。(我如何在不使用sp_executesql(动态查询)的情况下实现这一目标)?逻辑是创建两个表来存储两个输入数据,使用
CHARINDEX
存储每个输入的每个元素;从连接的结果中选择数据,使用表游标生成每一对,然后使用动态sql获得最终结果我一直在寻找不使用动态查询的方法。(我如何在不使用sp_executesql(动态查询)的情况下实现这一目标)以及
 CREATE Procedure ProceName
    (
        @OrderByField VARCHAR(100),
        @OrderDirection VARCHAR(100),

    )  
    As  
    Begin  

    Declare @SQL VARCHAR(MAX)

    if OBJECT_ID('Example1') is not null
    begin
    drop table Example
    end

    if OBJECT_ID('Example2') is not null
    begin
    drop table Example2
    end

    Create table Example1
    (
    id int identity(1,1),
    Field varchar(20)
    )

    Create table Example2
    (
    id int identity(1,1),
    OrderNumber varchar(10)
    )

    --iterate each element for both @OrderByField and @OrderDirection
    Declare @separator char(1)=','
    Declare @position int = 0
    Declare @name varchar(20)
    Set @OrderByField = @OrderByField + @separator 
---------------------------------------------------------------------------
         /*iterate each for @OrderByField */
---------------------------------------------------------------------------

    While CHARINDEX (@separator,@OrderByField,@position) != 0 
    BEGIN

    SET @name = SUBSTRING (@OrderByField,@position,CHARINDEX (@separator,@OrderByField,@position)-@position)

    SET @SQL = 'Insert into Example1([Field]) Values(' + char(39) + @name + char(39) + ')'
    EXEC(@SQL)

    SET @position = CHARINDEX(@separator,@OrderByField,@position)+1

    END


---------------------------------------------------------------------------
         /*iterate each for @OrderDirection */
---------------------------------------------------------------------------

    SET @position = 0 --do not forget to reset the position number

    Set @OrderDirection = @OrderDirection + @separator

    While CHARINDEX (@separator,@OrderDirection,@position) != 0 
    BEGIN

    SET @name = SUBSTRING (@OrderDirection,@position,CHARINDEX (@separator,@OrderDirection,@position)-@position)

    SET @SQL = 'Insert into Example2([OrderNumber]) Values(' + char(39) + @name + char(39)+ ')'
    EXEC(@SQL)

    SET @position = CHARINDEX(@separator,@OrderDirection,@position)+1

    END




Set @name = '' --reset the @name for the use of Cursor
declare @NewName varchar(500) =''


Declare row_cursor CURSOR
FOR
select 'Field'+a.Field + ' '+ case when b.OrderNumber = 0 then 'ASC' else 'DESC' end +',' as command
from Example1 as a 
inner join Example2 as b
on b.id = a.id


OPEN row_cursor
FETCH NEXT FROM row_cursor into @name

WHILE (@@FETCH_STATUS =0)
begin
Set @NewName = @NewName + @name

FETCH NEXT FROM row_cursor into @name
end
close row_cursor
deallocate row_cursor

SET @NewName = REVERSE(STUFF(REVERSE(@NewName),1,1,''))


SET @SQL = 'Select * From Table1 Order by ' + @NewName

--Print(@SQL)
EXEC (@SQL)

END