7 votes

Comment utiliser l'ordre par dans une procédure stockée sans utiliser le SQL dynamique ?

J'ai la procédure stockée MS SQL suivante. J'ai besoin de trier les résultats sans utiliser de SQL dynamique et de sp_executesql méthode

@Order by peut avoir les valeurs suivantes ProductName ASC , ProductName DESC , ProductCode ASC , VendorName DESC , VendorCode o ClientName

J'essayais d'utiliser ORDER BY CASE Est-ce qu'il y a un problème si le ProductName , ProductCode sont de type différent ?

ALTER PROCEDURE [dbo].[SortedReport]
(
    @ClientID INT,
    @RecordLimit,
    @FromDate DATETIME,
    @ToDate DATETIME,
    @OrderBy NVARCHAR(MAX)
)

AS
BEGIN

IF (@OrderBy IS NULL) BEGIN
    SET @OrderBy = 'ProductName';
END    

SELECT TOP (@RecordLimit) 
        sv.ClientID,
        sv.VendorID,
        sv.ProductID,
        sv.TransactionTime,
        sv.ClientName,
        sv.VendorName,
        sv.ProductName,
        sv.ProductCode,
        sv.VendorCode,
FROM SortedReportiew AS sv 
WHERE (sv.ClientID = @ClientID)
    AND (sv.TransactionTime >= @FromDate)
    AND (sv.TransactionTime < @Date)

Mise à jour :

La partie ci-dessous est-elle correcte ? réf. de aquí

ORDER BY 
    CASE @OrderBy WHEN 'ProductCode ASC' THEN ProductCode WHEN 'ProductCode DESC' THEN ProductCode END DESC,
    CASE @OrderBy WHEN 'ProductName ASC' THEN ProductName WHEN 'ProductName DESC' THEN ProductName END DESC,

13voto

Ocaso Protal Points 6025

Comme vous l'avez déjà dit : Utilisez ORDER BY CASE mais plusieurs fois pour éviter les problèmes liés aux différents types de colonnes :

...
ORDER BY 
 CASE WHEN @OrderBy ='ProductName ASC' THEN sv.ProductName END,
 CASE WHEN @OrderBy ='ProductName DESC' THEN sv.ProductName END DESC,
 CASE WHEN @OrderBy ='ProductCode ASC' THEN sv.ProductCode END,
 CASE WHEN @OrderBy ='ProductCode DESC' THEN sv.ProductCode END DESC,
 CASE WHEN @OrderBy ='VendorName ASC' THEN sv.VendorName END,
 CASE WHEN @OrderBy ='VendorName DESC' THEN sv.VendorName END DESC,
 CASE WHEN @OrderBy ='VendorCode' THEN sv.VendorCode END,
 CASE WHEN @OrderBy ='ClientName' THEN sv.ClientName END

EDIT :

J'ai mis à jour la requête pour qu'elle corresponde à votre nouvelle question. Je suppose que vous vouliez dire ProductCode ASC et ProductCode DESC ?

3voto

Andriy M Points 40395

Je comprends que le classement n'utilise qu'une seule colonne. Dans ce cas, je pourrais essayer quelque chose comme ceci :

  1. Split @OrderBy en @OrderByCol y @OrderByDir .

  2. Utilisez ce modèle :

    ...
    ORDER BY
      CASE @OrderByDir WHEN 'ASC' THEN
        CASE @OrderByCol
          WHEN 'Column1' THEN Column1
          WHEN 'Column2' THEN Column2
          ...
        END
      END ASC,
    
      CASE @OrderByDir WHEN 'DESC' THEN
        CASE @OrderByCol
          WHEN 'Column1' THEN Column1
          WHEN 'Column2' THEN Column2
          ...
        END
      END DESC

    Ou, si vous êtes sur SQL Server 2005+, peut-être celui-ci, comme alternative :

    WITH sorted AS (
      SELECT
         ... /* columns, omitted */
         Column1Order = ROW_NUMBER() OVER (ORDER BY Column1),
         Column2Order = ROW_NUMBER() OVER (ORDER BY Column2),
         ...
      FROM ...
    )
    SELECT ...
    FROM sorted
    ORDER BY
      CASE @OrderByCol
        WHEN 'Column1' THEN Column1Order
        WHEN 'Column2' THEN Column2Order
        ...
      END * CASE @OrderByDir WHEN 'DESC' THEN -1 ELSE 1 END

Comme @Greg Ogle l'a correctement souligné dans le commentaire, le premier modèle ne peut fonctionner que si les différents critères de tri sont de types compatibles, sinon l'instruction se brisera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X