Order by - Dónde está el error?

13/10/2008 - 14:58 por Don Juan | Informe spam
Hola a todos.
Este es el código:
Declare @OrderBy nvarchar(50)
Set @OrderBy = 'Cust_Country'

Select
Cust_id, Cust_Serv_Rep, Cust_Type, Cust_Country,
Cust_Name
FROM Customer
ORDER BY
CASE
WHEN @OrderBy = 'Cust_id' THEN Cust_id
WHEN @OrderBy = 'Cust_Serv_Rep' THEN Cust_Serv_Rep
WHEN @OrderBy = 'Cust_Type' THEN Cust_Type
WHEN @OrderBy = 'Cust_country' THEN Cust_Country
WHEN @OrderBy = 'Cust_Name' THEN Cust_Name
END
Este es el mensaje de error que tengo al querer hacer un order by
ustilizando una variable @OrderBy

Msg 245, Level 16, State 1, Line 5
Syntax error converting the nvarchar value 'Germany' to a column of data
type int.
He revisado las columnas muchas veces y los tipos de datos están correctos
el
Cust_id - INT,
Cust_Serv_Rep - nvarchar(50),
Cust_Type - nchar(20),
Cust_Country - nvarchar(50),
Cust_Name - nvarchar(250)
Cuando hago el Order by Cust_Country no tengo ningún problema los campos son
ordenados.
Cuando uso el CASE y ordeno una columna de tipo entero como el Cust_ID no
tengo problema, el problema es cuando quiero ordenar un tipo nvarchar o
char.

Si alguien puede darme una mano le agradeceré mucho, de lo contrario lo que
ando buscando es una forma de ordenar cuando el SQL recive una variable la
cual será el campo de orden.

1000 gracias!

Preguntas similare

Leer las respuestas

#1 Juan Diego Bueno
13/10/2008 - 15:16 | Informe spam
Hola Juan:

On 13 oct, 14:58, "Don Juan" wrote:
Mostrar la cita
Creo que tu problema reside en que usas el parámetro para un campo de
la query, cuando (que yo sepa) sólo puedes usarlo para valores.

Mecanismos para solucionar esto:

- Hacer el case en T-SQL dentro de una función de usuario que te
devuelva un tipo tabla con el resultado de la query. Eso sí, vas a
tener que hacer por cada case una query prácticamente idéntica excepto
en la parte del order by.
- Usar SQL Dinámico: Sería crear un procedimiento almacenado que
devuelva también ese resultado y generar la query dinámicamente.
Generarías una query dinámica que sustituyera el valor de @orderby por
el nombre del campo que desees. Para ello, revisa la sintaxis de
sp_executesql. Si te propongo el SP para ésto es porque las funciones
de usuario no permiten la ejecución dinámica de SQL. Un inconveniente
que puedes encontrar en esto es que pudiera haber inyección de código
SQL. Una forma simple de impedir esto es evaluar si @orderby es un
nombre de columna válido, haciendo una query sobre las vistas del
sistema (sys.columns o information_schema.columns) comprobando que
efectivamente, ese nombre de columna existe.

Un saludo
#2 Don Juan
13/10/2008 - 16:55 | Informe spam
Gracias...
Intenté esto y funciona:
ORDER BY
CASE WHEN @OrderBy = 'Cust_id' THEN Cust_id END DESC,
CASE WHEN @OrderBy = 'Cust_Serv_Rep' THEN Cust_Serv_Rep END DESC,
CASE WHEN @OrderBy = 'Cust_Type' THEN Cust_Type END DESC,
CASE WHEN @OrderBy = 'Cust_country' THEN Cust_Country END DESC,
CASE WHEN @OrderBy = 'Cust_Name' THEN Cust_Name END DESC

Ahora el problema que tendo es que DESC y ASC también deben estar en una
variable @Direction
y una línea así no funciona:
@Direction = 'DESC'
CASE WHEN @OrderBy = 'Cust_country' THEN Cust_Country END @Direction,

Me da error... alguna sugerencia?


"Don Juan" wrote in message
news:
Mostrar la cita
#3 Ele
13/10/2008 - 17:22 | Informe spam
Hola
haz una condicion if como son 2 valores posibles solo vas a repetir 2 veces
el mismo codigo
y lo pones si es Asc o Desc
ejemplo:
If @Direction = 'ASC'
ORDER BY
CASE WHEN @OrderBy = 'Cust_id' THEN Cust_id END ASC,
CASE WHEN @OrderBy = 'Cust_Serv_Rep' THEN Cust_Serv_Rep END ASC,
CASE WHEN @OrderBy = 'Cust_Type' THEN Cust_Type END ASC,
CASE WHEN @OrderBy = 'Cust_country' THEN Cust_Country END ASC,
CASE WHEN @OrderBy = 'Cust_Name' THEN Cust_Name END ASC
Else
ORDER BY
Mostrar la cita
"Don Juan" escribió en el mensaje
news:
Mostrar la cita
#4 Alejandro Mesa
14/10/2008 - 01:32 | Informe spam
Don Juan,

El problema esta cuando los tipos de datos devueltos por las partes THEN no
son compatibles. El tipo de dato que devuelve la funcion case, es el tipo de
mayor precedencia entre todos los tipos que participan en las partes THEN y
ELSE, por lo que cuando se devuelve un valor que no puede ser convertido
explicitamente hacia el tipo de mayor precedencia, entonces tienes un error.

Ejemplo:

DECLARE @i INT

SET @i = 2

select
CASE @i
when 1 then 1
when 2 then 'error'
else 1.00 end
go

Aqui tenemos tres tipos, entero, numerico y caracter. El tipo numerico es el
de mayor precedencia, por lo tanto si ejecutas este script con @i = 1, no
habra problema porque SQL Server convertira el valor 1 a numerico, pero si
ejecutas el script para @i = 2 entonces dara error porque el valor 'error' no
se puede convertir a numerico.

Ahora que sabes como funciona la funcion case, sabras que puedes arreglar el
problema convirtiendo explicitamente los valores para estos sean compatibles.
En tu caso, deberas convertir el valor entero a caracter para que este no sea
mas el de mayor precedencia.

Mostrar la cita
ORDER BY
CASE
WHEN @OrderBy = 'Cust_id' THEN cast(Cust_id as varchar(15))
WHEN @OrderBy = 'Cust_Serv_Rep' THEN Cust_Serv_Rep
WHEN @OrderBy = 'Cust_Type' THEN Cust_Type
WHEN @OrderBy = 'Cust_country' THEN Cust_Country
WHEN @OrderBy = 'Cust_Name' THEN Cust_Name
END


Cuidado al ordenar alfabeticamente, puesto que a veces resulta dificil de
comprender, como en el ejemplo que sigue.

SELECT *
FROM (SELECT '1A' AS c1 UNION ALL SELECT '12A' UNION ALL SELECT '13B') AS t
ORDER BY 1
GO

Otra forma seria convertiendo todos los tipos a sql_variant, pero igual,
mezclar diferentes tipos y ordenarlos alfabeticamente puede dar resultados no
esperados.

DECLARE @i INT

SET @i = 2

SELECT CASE @i
WHEN 1 THEN CAST(1 AS SQL_VARIANT)
WHEN 2 THEN CAST('error' AS SQL_VARIANT)
ELSE CAST(1.00 AS SQL_VARIANT)
END
go

Como ultimo, puedes utilizar sql dinamico. Solo ten en cuenta la posibilidad
de injeccion de codigo t-sql.


AMB


"Don Juan" wrote:

Mostrar la cita
#5 Don Juan
14/10/2008 - 08:48 | Informe spam
Muy bien explicado.
Muchas gracias Alejandro

"Alejandro Mesa" wrote in message
news:
Mostrar la cita
Ads by Google
Search Busqueda sugerida