2009-06-06 4 views
39

Je voudrais obtenir la fonctionnalité de CONNECTER PAR PRIOR d'ORACLE dans SQL SERVER 2000/2005/2008?Simulation de CONNECTER PAR AVANT de ORACLE dans SQL SERVER

S'il vous plaît aidez-moi

+0

Puisque vous semblez vouloir plus de détails, vous devrez nous dire quelques données sur la structure de la table et ce que vous essayez de faire. Si vous avez une requête Oracle existante, ce serait un bon début ... –

+2

@John, voir l'URL que j'ai posté dans ma réponse, http://www.ibm.com/developerworks/db2/library/techarticle/ dm-0510rielau/- il montre comment fonctionne CONNECT BY PRIOR (une syntaxe sympa mais réservée à Oracle pour obtenir des structures arborescentes) et comment obtenir le même effet avec des expressions de table communes (récursives), c'est-à-dire le mot clé WITH (qui est un standard SQL et implémenté dans IBM DB2, Microsoft SQL Server et le moteur PostgreSQL open-source dans la version 8.4). –

+0

@Alex: merci, j'ai vu votre message et lu l'article. Très joli article, et je peux voir pourquoi les utilisateurs d'Oracle pourraient aimer la syntaxe Oracle. Je préfère la syntaxe standard, car elle est plus générale. –

Répondre

59

La méthode standard SQL pour implémenter des requêtes récursives, mis en œuvre par exemple par IBM DB2 et SQL Server, est la clause WITH. Voir this article pour un exemple de traduction d'un CONNECT BY en un WITH (techniquement un récursif CTE) - l'exemple est pour DB2 mais je crois qu'il fonctionnera aussi sur SQL Server.

Editer: apparemment le demandeur d'origine nécessite un exemple spécifique, en voici un du site IBM dont j'ai déjà donné l'URL. Compte tenu d'une table:

CREATE TABLE emp(empid INTEGER NOT NULL PRIMARY KEY, 
       name VARCHAR(10), 
       salary DECIMAL(9, 2), 
       mgrid INTEGER); 

mgrid références empid est le gestionnaire d'un employé, la tâche est, obtenir les noms de tous ceux qui se rapporte directement ou indirectement à Joan. Dans Oracle, qui est un simple CONNECT:

SELECT name 
    FROM emp 
    START WITH name = 'Joan' 
    CONNECT BY PRIOR empid = mgrid 

Dans SQL Server, IBM DB2 ou PostgreSQL 8.4 (ainsi que dans la norme SQL, pour ce que ça vaut ;-), la solution parfaitement équivalente est plutôt une récursif requête (syntaxe plus complexe, mais, en fait, encore plus de puissance et de flexibilité):

WITH n(empid, name) AS 
    (SELECT empid, name 
    FROM emp 
    WHERE name = 'Joan' 
     UNION ALL 
    SELECT nplus1.empid, nplus1.name 
    FROM emp as nplus1, n 
    WHERE n.empid = nplus1.mgrid) 
SELECT name FROM n 

clause START WITH Oracle devient le premier imbriqué SELECT, le cas de base de la récursion, pour être UNION ed avec la partie récursive qui est juste un autre SELECT.

La syntaxe spécifique de SQL Server de WITH est bien sûr documentée sur MSDN, qui fournit également des directives et des limitations pour l'utilisation de ce mot-clé, ainsi que plusieurs exemples.

+1

S'il vous plaît expliquer avec un exemple. E.g. Prenez certains pays et déclare Comme Inde --State1 - Etat2 Australie --AusState1 --AusStae2 Je cherche la requête exacte –

+2

L'exemple que je montrai, à l'adresse http://www.ibm.com/developerworks/db2/library/techarticle/dm-0510rielau/, donne la requête exacte - la copier ici semble inutile quand vous pouvez simplement cliquer sur le lien! -) –

+0

** F ** section à [cette url] (https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql) était ce que je cherchais. –

1

Je n'ai pas utilisé de connexion auparavant, mais une recherche rapide montre qu'il est utilisé pour les structures arborescentes. Dans SQL Server, vous utilisez des expressions de table communes pour obtenir des fonctionnalités similaires.

+2

Veuillez expliquer avec un exemple. E.g. Prenez certains pays et les États Comme Inde --State1 - Etat2 Australie --AusState1 --AusStae2 –

10

@Alex Martelli La réponse est excellente! Mais il ne travailler que pour un élément à temps (WHERE name = 'Joan') Si vous prenez la clause WHERE, la requête renverra toutes les lignes ensemble de racines ...

j'ai changé un peu pour ma situation, il peut montre l'arbre entier pour une table.

définition de la table

:

CREATE TABLE [dbo].[mar_categories] ( 
    [category] int IDENTITY(1,1) NOT NULL, 
    [name]  varchar(50) NOT NULL, 
    [level]  int NOT NULL, 
    [action] int NOT NULL, 
    [parent] int NULL, 
    CONSTRAINT [XPK_mar_categories] PRIMARY KEY([category]) 
) 

(level est littéralement le niveau d'une catégorie 0: racine, 1: premier niveau après la racine, ...)

et la requête: devrait être quelque chose comme

WITH n(category, name, level, parent, concatenador) AS 
(
    SELECT category, name, level, parent, '('+CONVERT(VARCHAR (MAX), category)+' - '+CONVERT(VARCHAR (MAX), level)+')' as concatenador 
    FROM mar_categories 
    WHERE parent is null 
     UNION ALL 
    SELECT m.category, m.name, m.level, m.parent, n.concatenador+' * ('+CONVERT (VARCHAR (MAX), case when ISNULL(m.parent, 0) = 0 then 0 else m.category END)+' - '+CONVERT(VARCHAR (MAX), m.level)+')' as concatenador 
    FROM mar_categories as m, n 
    WHERE n.category = m.parent 
) 
SELECT distinct * FROM n ORDER BY concatenador asc 

(Vous n'avez pas besoin de concaténer le domaine level, je ne juste faire plus lisible)

la réponse à cette requête:

sql return

J'espère que cela aide quelqu'un!

maintenant, je me demande comment faire sur MySQL ... ^^

+0

j'ai eu un problème bizarre d'adapter votre code, avec un non les mêmes types de données sur le délimiteur et la colonne récursive .... mais il a trié, juste en définissant explicitement la première longueur .... merci pour l'aide! –

+0

Est-il possible d'éviter la construction d'un chemin à partir d'une chaîne ('concatenador') pour obtenir une structure arborescente (donc chaque valeur de sous-feuille est regroupée sans trous par un autre élément)? Oracle 'connect by' construire de telle manière gratuitement. – gavenkoa

Questions connexes