você pode parametrizar ordem de classificação em um servidor SQL preparada declaração?

StackOverflow https://stackoverflow.com/questions/467034

Pergunta

Eu tenho um sistema web Net com um front-end VB.Net conversando com um back-end SQL Server 2005 sobre ADO.Net. Essencialmente, o que eu quero fazer é esta:

Dim command As SqlCommand = New SqlCommand("", connection)
command.CommandText = "SELECT * FROM someTable ORDER BY orderValue @SortOrder"
Dim sortParam As SqlParameter = New SqlParameter("@SortOrder", SqlDbType.varChar, 3)
sortParam.Value = "ASC"
command.Parameters.Add(sortParam)
command.Prepare()
reader = command.ExecuteReader()

Onde a ordem de classificação seria passado no meio de uma string de consulta ou algo assim. Este código lança "sintaxe incorreta próximo '@SortOrder'. Statement (s) não pode ser preparado."

É isto mesmo possível, ou tenho algum erro de sintaxe muito burro eu não estou vendo?

(E, sim, o cliente só está em execução .NET 2.0, pelo que as soluções baseadas em LINQ não vai funcionar, infelizmente.

Obrigado, todos!

Atualização / resposta:

Bem, isso é o que eu pensava. Obrigado pela verificação de sanidade, todo mundo. (Para alguns contexto, a cadeia de comando está sendo construído de forma dinâmica, mas nós estamos mudando o sistema em uma direção declaração mais preparado, e este foi um dos casos extremos eu não sabia que era possível.

Mais uma vez obrigado!

Foi útil?

Solução

Não, isso não vai funcionar.

Existem duas possibilidades que eu posso pensar direito em cima da minha cabeça para fazer o que você está tentando fazer:

  1. construir a string SQL dinamicamente
  2. retornar uma tabela de dados de sua consulta, e depois usar a View para fazer a sua classificação.

Com mais 6 anos ou mais de experiência (mais versões SQL Server), eu tenho uma maneira de fazer isso.

DECLARE @SortByIdASC AS INT;
SET @SortByIdASC = 1;
WITH cte AS (
SELECT Id, Foo, Bar
      , ROW_NUMBER() OVER (ORDER BY Id ASC) AS IdSortAsc
      , ROW_NUMBER() OVER (ORDER BY Id DESC) AS IdSortDesc 
   FROM MyTable
)

SELECT Id, Foo, Bar
   FROM cte 
   ORDER BY CASE WHEN @SortByIdASC = 1 THEN IdSortAsc
                 WHEN @SortByIdASC = 2 THEN IdSortDesc 
                 ELSE ''
                 END 
           , Foo, Bar 

Isso também permite a ordenação cima, para baixo, ou mesmo excluir essa coluna em particular a partir da dada ordem de classificação.

Outras dicas

Embora seja possível atualizar as colunas usadas em uma espécie. Veja o seguinte exemplo:

declare @fname int,@lname int

select @fname=1,@lname=0

select * from [user]
order by case when @Fname=1 then firstname when @lname=1 then lastname end

Eu não acho que você pode usar esta técnica para modificar a ordem de classificação, mas você pode pelo menos mudar as colunas a sua classificação diante. Pelo menos quando eu tento obter queixas sobre sintaxe com SQL 2005

Você pode de forma semelhante a uma mensagem existente.

declare @firstSortField int, @secondSortField int
set @firstSortField = 1
set @secondSortField = 3

select firstName, lastName, phoneNumber
from customers
order by 
    case @firstSortField when 1 then firstName when 2 then lastName when 3 then phoneNumber else null end, 
    case @secondSortField when 1 then firstName when 2 then lastName when 3 then phoneNumber else null end

Eu não acho que é possível, único parâmetro valores podem ser preparadas.

Não, você precisa construí-lo na consulta SQL de cada vez, ou se você tem um sub conjunto de ordens de classificação, cache o objeto de comando para estes e re-uso como suites.

O curto ansswer para a questão, porém, é "Não"

Este faz exatamente o que você pediu e nunca coloca cordas inseridos pelo usuário em qualquer lugar perto do banco de dados.

//get the requested order from the query string
string sortOrderRequest = request["SortOrder"].ToUpper();
string sortParam = "";
if ( sortOrderRequest.Equals("ASC"))
  sortParam = " order by ordervalue ASC ";
else if (sortOrderRequest.Equals("DESC"))
  sortParam = " order by ordervalue DESC ";

Dim command As SqlCommand = New SqlCommand("", connection)
command.CommandText = "SELECT * FROM someTable " + sortParam;
command.Prepare()
reader = command.ExecuteReader()

Claro que pode fazer. Criar duas colunas alias, SortASC e SortDESC, preenchê-los com o que quiser, e classificar-los.

-- Testcase setup
DECLARE @OrderASC bit
SET @OrderASC = 0

-- Statement required
SELECT
    Users.*,
    CASE @OrderASC WHEN 1 THEN Users.Alias ELSE null END AS _SortASC,
    CASE @OrderASC WHEN 0 THEN Users.Alias ELSE null END AS _SortDESC
FROM Users
ORDER BY _SortASC, _SortDESC DESC

Eu estendi a resposta aceita para alcançar uma solução eficaz para parametrizar cláusula de ordem em uma consulta SQL. Aqui está um código de exemplo:

DECLARE @Sorting VARCHAR(200) = 'CreationTime ASC'

SELECT v.*, 
CASE WHEN @Sorting = 'CreationTime ASC' THEN ROW_NUMBER() OVER (ORDER BY v.CreationTime ASC) 
     WHEN @Sorting = 'CreationTime DESC' THEN ROW_NUMBER() OVER (ORDER BY v.CreationTime DESC) 
                                         ELSE ROW_NUMBER() OVER (ORDER BY v.Id ASC) END AS rownum

FROM Vehicles v ORDER BY rownum 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top