2009-01-20 9 views
3

Si j'écris un sproc dans ce format, sql le fera-t-il efficacement ou le sql 'weaving' sera-t-il fait côté serveur (.net)?Est-ce une requête SQL Server efficace?

Note: ceci est juste une idée approximative de ce que ma requête ressemble, il y a plus « si » les clauses de la construction ma requête que j'exécute en utilisant « exec »

declare @sql nvarchar(4000) 
declare @order nvarchar(4000) 


set @sql = 'select id, name' 
set @sql = @sql + ' ....' 

if(@sortOrder) 
    set @order = 'order by name desc' 

exec @sql + @order 

Répondre

0

Avez-vous un bon raison de le faire comme SQL dynamique?

J'ai fait ce que vous avez déjà dans SQL Server et ça marche bien; il est probablement plus sûr (en fonction de l'utilisation) que de passer en SQL complètement formé à un proc qui l'exécute à l'aveugle.

Si vous utilisez SQL 2k5 ou 2k8, vous pouvez utiliser nvarchar (max) pour des chaînes plus longues.

-1

Oui.

Il compile dans la commande "exec". La différence de vitesse devrait être minime entre cela, et tout faire du côté .NET.

À un moment donné, il compile le code SQL dans un code interne. Cela peut arriver quand .NET le pousse, ou après.

4

Au lieu de créer une chaîne SQL, pourquoi ne pas utiliser une instruction case dans l'ordre?

par exemple. (En supposant un est le tri par la première et/ou nom de famille sur une table avec des champs FirstName et LastName)

order by 
    case 
    when @sortExpression = 'lastname asc' then CAST(LastName as sql_variant) 
    when @sortExpression = 'firstname asc' then CAST(FirstName as sql_variant) 
    end asc, 
    case 
    when @sortExpression = 'lastname desc' then CAST(LastName as sql_variant) 
    when @sortExpression = 'firstname desc' then CAST(FirstName as sql_variant) 
    end desc 

De plus, si votre commande par clause est différent à chaque fois via SQL dynamique, le plan de requête ne sera jamais réutilisé.

+0

Le type des colonnes doit être la même (NULL les ones non utilisés): QUAND ORDER BY @Order CASE 1 ALORS [ DateOfBirth] ELSE NULL END , CASE @Order QUAND 2 ALORS [DateOfBirth] ELSE NULL END DESC , CASE @Order QUAND 3 THEN [LastName] ELSE NULL END , CASE @Order QUAND 4 THEN [LastName] ELSE NULL END DESC – IDisposable

+0

Non, ils ne le font pas. Tant que vous CAST à sql_variant, les colonnes peuvent toutes être de types différents dans le même CAS et vous n'avez pas besoin de définir quoi que ce soit à NULL. Essayez-le, ça fonctionne. Je l'ai fait plusieurs fois. –

+0

Si vous convertissez en sql_variant, la logique de tri sera basée sur une chaîne, de sorte que les valeurs numériques ne seront pas triées comme prévu. – IDisposable

-5

Je voudrais construire le reste de la requête jusqu'à la commande par exemple.

@sql = 'SELECT id, name FROM myTable ORDER BY ' + @order 

... et de passer le nom et la direction de la colonne à proc. Cette façon de faire est plus sûre car peu de choses peuvent être passées à une clause order by pour causer des dommages.

Pour répondre à votre question, c'est efficace.

+1

>> car peu de choses peuvent être passées à une clause order by pour causer des dommages. Wow, juste wow – SQLMenace

+1

Mauvaise idée, cependant, vous pouvez passer dans l'ordre en entier, puis en fonction de la valeur de cet entier, trier par une liste de colonnes prédéfinies correspondant à ces valeurs entières. – Kibbee

+1

Puis-je commander vos tables par "nom; DROP TABLE myTable" s'il vous plaît? – MatBailie

1

Je vois deux meilleures façons de le faire. Au lieu d'utiliser une requête SQL dynamique, j'utiliser une instruction SQL réelle dans une procédure stockée, tubé par les choses que vous voulez commander par:

select 
    t.* 
from 
    table as t 
order by 
    case @val 
    when 1 then column1 
    when 2 then column2 
    end 

Si vous trouvez que l'ordre par trop dynamique et doit être construit ou est easer de le faire, alors je créerais une fonction de table d'une valeur qui renvoie le jeu, puis créer une instruction SQL dynamique contre que:

select 
    t.* 
from 
    xfn_Function(@arg1, @arg2) as t 
order by 
    t.col1, t.col2 

si bien sûr, t.col1, t .col2, etc, etc, sont générés dynamiquement avant d'envoyer le tout au serveur.

2

Le moyen le plus simple, le plus simple, le plus simple et le plus optimisable est d'avoir des instructions SQL complètes pour chaque option.

+0

triste mais il semble être vrai .. –

0

Pour répondre spécifiquement à votre question, il n'y aura aucune différence de performance entre une instruction SQL dynamique qui est formée dans votre couche .Net et exactement la même chaîne SQL qui est formée dans un proc.

0

Le plus efficace consiste à obtenir les données souhaitées dans la base de données, puis à gérer le tri dans votre application. Changer la commande par ne va pas changer la quantité de données. Si l'utilisateur change l'ordre de tri, pourquoi faire un autre voyage dans la base de données?

0

La performance de requête dynamique est presque équivalente au tissage côté serveur. Si vous ne trouvez pas d'autre moyen d'éviter une requête dynamique, imbriquez-la du côté serveur.

suivant fonctionne aussi dans le cas où vous n'avez pas beaucoup de "si"

if(@sortorder = 'name') select id, name from tbl order by name asc 
if(@sortorder = 'id') select id, name from tbl order by id asc 
Questions connexes