2012-09-15 3 views
1

Voici un exemple de ce que j'essaie d'accomplir.Sélection SQL avec la clause IN

declare @MenuIDs varchar(max) = '1,2,3,4'; 

SELECT 
    tMenuMain.MenuId, 
    tMenuMain.MenuRank 
INTO #TempRankTable 
FROM tMenuMain 
WHERE tMenuMain.MenuId IN (@MenuIDs); 

select * from #TempRankTable;      

La valeur @MenuIDs varaible est en fait un paramètre sproc. (Je viens de le déclarer dans l'exemple pour expliquer)

Comment faire fonctionner la sélection, puisque la commande IN ne fonctionne qu'avec des valeurs séparées par des virgules et pas seulement une chaîne. L'autre problème auquel je suis confronté est que tMenuMain.MenuId est une colonne entière. Est-il possible de faire un CAST dans cette situation?

+0

certainement pas facile! voir [ICI] (http://www.sommarskog.se/arrays-in-sql-2008.html). Est-ce que le menuID doit être dans une liste séparée par des virgules comme ça? Y at-il de toute façon que vous pourriez les mettre dans une seule table de colonne en premier? – whytheq

Répondre

2

Vous pouvez déclarer une petite fonction d'assistance qui "mappe" la chaîne à une table;

CREATE FUNCTION dbo.str2ints(@str nvarchar(max)) 
RETURNS @ints TABLE (val INT) 
AS 
BEGIN 
    DECLARE @xml XML 
    SET @xml = '<root><str>' + REPLACE(@str, ',', '</str><str>') + '</str></root>' 
    INSERT INTO @ints(val) 
    SELECT str.value('.', 'int') 
    FROM @xml.nodes('//str') AS RECORDS(str) 
    RETURN 
END 

Ensuite, vous pouvez réécrire votre fonction pour utiliser cette fonction pour la division;

declare @MenuIDs varchar(max) = '1,2,3,4'; 

SELECT 
    tMenuMain.MenuId, 
    tMenuMain.MenuRank 
INTO #TempRankTable 
FROM tMenuMain 
WHERE tMenuMain.MenuId IN (SELECT * FROM dbo.str2ints(@MenuIDs)); 

select * from #TempRankTable; 
+0

Existe-t-il une raison spécifique pour laquelle la fonction triera les valeurs? Si je réussis '3,2,4,1', j'obtiens les résultats dans le même ordre que lorsque je passe '1,2,3,4'. – JAT

1

Vous devez utiliser SQL dynamique et vue:

declare @MenuIDs varchar(max) = '1,2,3,4'; 
declare @SQL varchar(max); 

set @SQL = 'create view vTab as 
      SELECT tMenuMain.MenuId, tMenuMain.MenuRank     
      FROM tMenuMain 
      WHERE tMenuMain.MenuId IN ('[email protected]+')'; 
/* 
    Select in @SQL should look like: 
      create view vTab as 
      SELECT tMenuMain.MenuId, tMenuMain.MenuRank     
      FROM tMenuMain 
      WHERE tMenuMain.MenuId IN (1,2,3,4) 
*/ 

exec(@SQL) 

select * 
into #TempRankTable 
from vTab 

drop view vTab 

select * from #TempRankTable; 

ou si vous pouvez create table avant insérer

declare @MenuIDs varchar(max) = '1,2,3,4'; 
declare @SQL varchar(max); 

create table #TempRankTable 
(
    MenuId ... 
    MenuRank ... 
) 

set @SQL = 'insert into #TempRankTable(MenuId,MenuRank) 
      SELECT tMenuMain.MenuId, tMenuMain.MenuRank     
      FROM tMenuMain 
      WHERE tMenuMain.MenuId IN ('[email protected]+')'; 
/* 
    Select in @SQL should look like: 
      insert into #TempRankTable(MenuId,MenuRank) 
      SELECT tMenuMain.MenuId, tMenuMain.MenuRank     
      FROM tMenuMain 
      WHERE tMenuMain.MenuId IN (1,2,3,4) 
*/ 

exec(@SQL) 

select * from #TempRankTable; 
+0

J'ai déjà essayé ça; J'obtiens cette erreur: (4 ligne (s) affectée) Msg 208, niveau 16, état 0, ligne 17 Nom d'objet non valide '#TempRankTable'. – JAT

+0

J'ai édité le post. Essayez cette solution. – Parado

+0

@Parado réponse originale aurait été ok mais il fallait créer la table temp d'abord 'CREATE TABLE #TempRankTable (MenuId INT, MenuRank INT)' avant le SQL dynamique. et le 'INSERT INTO' de cette table dans le SQL dynamique – whytheq

0

Il est facile et propre à faire ce que vous voulez. La question suivante contient beaucoup de solutions de contournement, en utilisant, par exemple, XML ou une fonction locale qui divise les valeurs suivantes:

Une alternative laid mais facile serait d'utiliser la méthode CHARINDEX pour vérifier si ',' + tMenuMain.MenuId + ',' est contenu dans ,1,2,3,4, (notez les virgules de début et de fin).