2009-12-03 3 views
6

J'ai 10 tables que je joins pour créer une vue. Je ne sélectionne que l'ID de chaque table, mais dans la vue, chaque ID peut s'afficher plusieurs fois, mais la combinaison de tous les ID sera toujours unique. Y a-t-il un moyen de créer une autre colonne dans cette vue qui sera un identifiant unique? Je voudrais pouvoir stocker l'identifiant unique et l'utiliser pour interroger la vue afin d'obtenir tous les autres ID.Est-il possible de créer un ID unique dans une vue SQL Server qui restera le même chaque fois que la vue est appelée?

Répondre

1

Non, vous ne pouvez pas faire cela dans une vue, ce que vous pouvez faire est de créer une table temporaire pour contenir toutes ces informations et créer une clé ou un identifiant unique pour chaque ligne.

+1

+ 1'ed. Mais, s'il veut que cette information persiste, ce ne serait pas une table temporaire, ce serait une table réelle. –

+0

@Mark oui vous avez raison :). – JonH

1

Je pense que vous pouvez le faire en utilisant ROW_NUMBER(), au moins si vous pouvez garantir un ordre de la vue. Par exemple:

SELECT 
    ROW_NUMBER() OVER (ORDER BY col1, col2, col3) as UniqueId 
FROM <lotsa joins> 

Tant que l'ordre reste le même, et seuls les champs sont ajoutés à la fin, l'identifiant sera unique.

+0

Cela ne garantit pas que les chiffres sont les mêmes à chaque fois. Si j'ai (1, 1, 1) et (3, 3, 3) ils seront respectivement 1 et 2. Si j'ajoute ensuite (2, 2, 2) alors la ligne (3, 3, 3) va maintenant devenir 3 et non 2. –

+0

@Tom H: C'est pourquoi j'ai mis "si vous pouvez garantir une commande" en haut de ma réponse :) – Andomar

+0

Garantir une commande ne le fait pas si. Ce n'est pas seulement l'ordre des lignes, c'est aussi qu'aucune nouvelle ligne ne peut être ajoutée et que les lignes ne peuvent pas être changées. En d'autres termes, les données doivent être complètement statiques à l'exception de l'ajout de lignes à la toute fin dans la commande. –

0

Le fait que vous essayiez de faire cela indique des problèmes beaucoup plus importants dans la conception de la base de données et/ou dans l'architecture de l'application. Comme vous avez 10 tables et je vais deviner que les concepteurs de DB juste giflés sur ID INT IDENTITY à toutes les tables que vous finirez par avoir environ (2^31)^10 lignes possibles dans la table.

Le seul type de données que je peux penser qui pourrait couvrir ce nombre serait de traduire tous les entiers en chaînes 0-padded et les mettre tous ensemble comme un grand CHAR. Je suppose cependant que votre vrai problème n'est pas d'obtenir cet ID pour une vue, mais une autre chose que vous essayez de faire, qui est la question que vous devriez poser. Juste une intuition cependant.

+0

Oui, je suis tout à fait d'accord, malheureusement c'est quelque chose que je suis coincé avec, juste à la recherche de la meilleure façon de s'y prendre. C'est une base de données de véhicules, donc il y a plus de 50 tables contenant chacune leurs propres ID qui peuvent toutes être jointes à la suivante. J'essaye juste de rassembler l'information de base/les identifiants afin d'exécuter d'autres requêtes de: VehicleID, BedID, BodyStyleID, BrakeID, DriveTypeID, EngineConfigID, etc ... vraiment pas joli. – Brendo

0

Une possibilité serait d'appeler une fonction de votre vue qui calcule un code de hachage sur toutes les colonnes ID. Si vous utilisez un algorithme de hachage cryptographique décent, les probabilités d'une collision sont minimes (probablement plus probable que le disque délivre de mauvaises données). Encore plus simple, vous pouvez bien sûr concaténer les différents identifiants en un identifiant unique, beaucoup plus grand, peut-être en colonne binaire ou varbinaire.

Le stockage de cet ID et la possibilité d'effectuer une requête par rapport à celui-ci seraient un peu plus laborieux. Je ne peux pas penser à un moyen de le calculer et de le stocker à partir d'une vue. Vous auriez probablement besoin d'une procédure stockée pour le créer en premier; les détails dépendent fortement des spécificités de votre application.

4

J'avais un problème similaire où j'avais besoin d'établir une hiérarchie entre plusieurs tables. Si vous utilisez un entier comme id dans chacune des tables, vous pouvez simplement convertir les identifiants de chaque table en un varchar et les préfixer avec une lettre différente pour chaque table. Par exemple

CREATE VIEW LocationHierarchy as

SELECT 'C' + CONVERT(VARCHAR,[Id]) as Id 
     ,[Name] 
     ,'S' + CONVERT(VARCHAR,[State]) as parent 
    FROM [City] 
    UNION 
    SELECT 'S' + CONVERT(VARCHAR,[Id]) as Id 
     ,[Name] 
     ,'C' + CONVERT(VARCHAR,[Suburb]) as parent 
    FROM [Suburb] 

etc

L'efficacité de cette solution dépendra de la taille de votre ensemble de données est.

+6

@tamago Il est toujours utile pour les utilisateurs comme moi qui étudient un sujet similaire et cherchent des réponses. –

1

Oui, récemment, j'ai eu la même exigence.

Lors de la création de la vue, conservez l'instruction select comme TEMP_TABLE, puis utilisez la fonction Row_number() sur ce TEMP_TABLE.

Voici un exemple:

CREATE VIEW VIEW_NM 
AS 
SELECT Row_number() OVER(ORDER BY column_nm DESC) AS 'RowNumber' FROM 
(SELECT COL1,COL2 FROM TABLE1 
UNION 
SELECT COL1,COL2 FROM TABLE2 
) AS TEMP_TABLE; 
Questions connexes