IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Déclarer une variable de façon identique à la définition d'un champ d'une table.


Sujet :

Développement SQL Server

  1. #1
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2010
    Messages
    185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 185
    Points : 167
    Points
    167
    Par défaut Déclarer une variable de façon identique à la définition d'un champ d'une table.
    Bonjour,
    J'ai vu faire cela avec Oracle mais est-ce possible avec SQL server ? (j'ai cherché mais pas vraiment trouvé)

    Un bon exemple vaut mieux que de long discourt :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TABLE [dbo].[tblMaTable]
    (
    	[ID]			[int] IDENTITY(1,1)	NOT NULL,
    	[nvcLabel]		[nvarchar](50)		NOT NULL,
    	[bitIsActive]	[bit]				NOT NULL DEFAULT 1
    	CONSTRAINT [PK_tblBoatTest] PRIMARY KEY CLUSTERED
    	(
    		[ID] ASC
    	)
    ) ON [PRIMARY]
     
    CREATE TRIGGER [dbo].[trgMaTable_U] ON tblBoatTest INSTEAD OF UPDATE AS 
    DECLARE @nvcLabel nvarchar(50)
    ...

    Si demain je change dans la longueur de mon champ dans la table, je dois aussi penser à changer la longueur de ma variable dans mon trigger... Mais s'il n'y avait que le trigger ça irait mais il y a aussi les fonctions, les procédures stockées...

    Y a-t-il un moyen de faire un lien entre les deux de telle façon à ce que le changement du champ dans la table impacte directement dans le reste de la base de données, triggers, fonctions, procédures...
    Quelque chose comme :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    DECLARE @nvcLabel LIKE tblMaTable.nvcLabel ;


    Idem pour un enregistrement d'une table, quelque chose comme :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    DECLARE @recMaVariable LIKE DEFINITION(tblMaTable);

    Merci

  2. #2
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    La technique d'Oracle permettant de déclarer un type par référence au type d'une colonne d'une table Exemple :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    DECLARE v_empId employe.empid%TYPE;
    N'existe pas sous SQL Server.

    Sous SQL Server vous pouvez créer des type utilisateur ( ou alias de type) commesuit :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
     CREATE TYPE ut_Libelle VRACHAR(50) NULL;
    Vous pouvez ensuite "factoriser" et réutiliser cet alias de type dans diverses tables (DDL), Procédures, fonction, Trigger etc.. (DML)

    Attention :
    - Créer et utiliser un type défini par l'utilisateur est quelque chose de très simple et facile..
    - Modifier un type utilisateur déjà référencée est une autres histoire, qui souvent s'avère laborieuse (mais toujours faisable). L'instruction ALTER TYPE n'existe pas !

    A+

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 897
    Points : 53 135
    Points
    53 135
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par ypelissier Voir le message
    Bonjour,
    J'ai vu faire cela avec Oracle mais est-ce possible avec SQL server ? (j'ai cherché mais pas vraiment trouvé)
    Oracle n'a jamais voulu implémenté ce que la norme SQL appelle le CREATE DOMAIN et qui permet de disposer de types de données indépendant des objets dans lesquels ils sont placés.
    Lorsque INGRES à été créé, c'est la notion deTYPE qui était plus à la mode; or SQL Server est un héritier de INGRES via Sybase.

    Vous devez donc créer vos types de données AVANT de créer vos tables, vues, procédures... et les utilisez dans la définition DDL de vos objets.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TYPE dbo.DN_POURCENT FROM FLOAT;
    CREATE TYPE dbo.DN_ID FROM BIGINT;
    CREATE TYPE dbo.DA_LIBELLE FROM VARCHAR(64);
    CREATE TYPE dbo.DN_PRIX FROM DECIMAL(16,2);
    GO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TABLE dbo.T_PRODUIT_PRD
    (PRD_ID           dbo.DN_ID IDENTITY PRIMARY KEY,
     PRD_DESIGNATION  dbo.DA_LIBELLE NOT NULL,
     PRD_PRIX         dbo.DN_PRIX NOT NULL,
     PRD_RABAIS       dbo.DN_POURCENT NOT NULL DEFAULT 0);
    GO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE PROCEDURE dbo.P_SOLDES @PRD_RABAIS dbo.DN_POURCENT
    AS
    SELECT *
    FROM   dbo.T_PRODUIT_PRD
    WHERE  PRD_RABAIS = @PRD_RABAIS;
    GO
    Pour apprendre SQL Server, lisez notre livre : http://www.amazon.fr/dp/2212135920/

    A +

  4. #4
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2010
    Messages
    185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 185
    Points : 167
    Points
    167
    Par défaut Oui mais non...
    Bonjour à vous 2,
    Merci de vos réponses qui m'éclairent d'un jour nouveau sur SQL Server mais ce jour n'est pas une lumière pour moi car je trouve cette organisation d'un complexe dans son application et surtout dans son évolution.

    En effet, l'idée que j'avais croisée chez Oracle, et à laquelle j'avais pas mal adhéré, c'est de pouvoir à ce champ défini dans la table directement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DECLARE v_empId employe.empid%TYPE;
    Dès que je change le champ empid de la table employe, c'est automatiquement impacté dans toute la base de données sans autre intervention que celle de modification du champ dans la base de données.

    Maintenant, avec SQL Server, vous me dites qu'il faut définir ses types utilisateurs mais que, comme le dit ci bien hmira
    Attention :
    - Créer et utiliser un type défini par l'utilisateur est quelque chose de très simple et facile..
    - Modifier un type utilisateur déjà référencée est une autres histoire, qui souvent s'avère laborieuse (mais toujours faisable). L'instruction ALTER TYPE n'existe pas !
    Ce qui fait qu'aujourd'hui, je défini un type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TYPE dbo.DA_LIBELLE FROM VARCHAR(64);
    Dans la création de ma table j'ai donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PRD_DESIGNATION dbo.DA_LIBELLE NOT NULL
    Et dans mes fonctions et procédure stockées j'utilise la déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DECLARE @Libelle AS dbo.DA_LIBELLE
    Jusque là tout va bien, ma base vie bien jusqu'au jour où on me demande d'augmenter la taille de ce champ (ça a beau être prévu à la base, ça arrivent toujours ces choses là, en cours de projet comme en projet terminé depuis plusieurs années).

    Bref, je ne peux pas faire de pour le redéfinir.

    2 options s'offrent à moi :
    [LIST=1][*]Supprimer la définition et la refaire,[*]Ajouter une nouvelle définition et l'utiliser dans la table...

    La première solution n'est pas possible car elle est utilisée par la table... et les fonctions et les procédures...... Un message d'erreur s'affiche quand je tente de le faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Cannot drop type 'DA_LIBELLE' because it is being referenced by object 'T_PRODUIT_PRD'. There may be other objects that reference this type.
    OK donc je supprime la table pour pouvoir supprimer le type et refaire tout ça avec ma nouvelle définition... Ah oui mais j'ai des liens... que je peux désactiver... OK Oui mais surtout j'ai des données maintenant que la base est en production !!! Que je peux copier dans une autre table, sans utiliser le type à supprimer... Arriver là, il reste les fonctions et les procédures qui empêchent de supprimer le type. Donc les supprimer pour enfin supprimer le type.
    Ceci fait, il faut tout refaire dans l'autre sens en changeant le TYPE.

    Je passe bien sûr allègrement sur la notion de "factorisation", tel que l'évoque hmira, qui, dans ce cas, impactera plusieurs tables donc d'autant plus de travail à réaliser, sans pour autant être pertinent de réaliser cette impact sur toutes les tables

    En gros j'ai l'impression que je refais tout le boulot pour la modification d'un champ.
    Long, fastidieux, risqué car beaucoup de manipulation DONT des données...

    Je regarde donc la seconde solution...
    OK je crée un nouveau type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TYPE dbo.DA_LIBELLE2 FROM VARCHAR(100);
    Du coup je peux adapter ma table
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE MaTable ALTER COLUMN PRD_DESIGNATION dbo.DA_LIBELLE2 NOT NULL
    OK mais toutes mes fonctions et procédures sont à refaire avec le nouveau type, j'y gagne rien en terme de recherche et d'intervention sur toutes les fonctions et procédures qui l'utilise.
    Certes, c'est moins de travail que la première solution et c'est moins risqué car il n'y a pas de manipulations de données.

    En fait non, pour tout avouer, je pense gagner quand même quelque chose d'essentiel, c'est l'assurance que ma base de données sera homogène dans son intégralité (et c'est déjà bien) mais je crains que cette assurance ne soit pas comprise par le client lorsqu'il faudra lui annoncer la quantité de travail à réaliser "juste" pour allonger son champ (ça m'est déjà arrivé sans avoir utilisé les types justement)...

    Néanmoins, je rappelle quand même le but de la question initiale, avoir une maintenance évolutive simple et je n'ai franchement pas l'impression d'y être comme avec Oracle...

    Alors qu'à la manière d'Oracle, franchement c'était beaucoup plus simple. C'est dommage car ces derniers temps je me disais que SQL Server était plus simple qu'Oracle mais là je dois avouer qu'il y aurait bien une amélioration.

    A moins qu'il n'y ai d'autres aspects que je n'aurais pas vu ou compris, je trouve cette mise en œuvre complexe pour une réponse toute simple telle que l'a faite Oracle.

    SQLpro, hmira, je ne vous jette pas la pierre quand à votre réponse tout à fait adaptée à ce que je craignais avoir entrevu sur le internet, à savoir l'utilisation des types et je sais que c'est un vœux pieux que de voir cette évolution arriver un jour sur SQL Server tant le poids de l'héritage est présent pour la compatibilité descendante des systèmes.

    Merci en tout cas à vous pour vos promptes réponses.

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 897
    Points : 53 135
    Points
    53 135
    Billets dans le blog
    6
    Par défaut
    Il n'y a pas de miracle et tous les SGBDR sont à même niveau sur ce point :
    1) changer le type d'une colonne d'une table contenant des données oblige à migrer les données. Le plus simple est la séquence suivante :
    • ALTER TABLE MaTable ADD NEW_COLONNE NEW_TYPE;
    • UPDATE MaTable SET NEW_COLONNE = CAST(OLD_COLONNE AS NEW_TYPE);
    • ALTER TABLE MaTable DROP COLUMN OLD_COLONNE;
    • ALTER TABLE MaTable ADD OLD_COLONNE NEW_TYPE;
    • UPDATE MaTable SET OLD_COLONNE = NEW_COLONNE;
    • ALTER TABLE MaTable DROP COLUMN NEW_COLONNE;

    Et s'il y a des contraintes et index afférente à cette colonne, les débrancher puis les rebrancher.

    En ce qui concerne les requêtes, vues, procédures, déclencheurs et autres fonctions UDF, il n'y a aucun risque d'utilisation des TYPE puisque c'est du compilé.

    A +

  6. #6
    Membre habitué
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2010
    Messages
    185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 185
    Points : 167
    Points
    167
    Par défaut
    OK.
    Merci.
    Problème résolu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Champ dans une variable
    Par Winguy dans le forum IHM
    Réponses: 3
    Dernier message: 30/03/2008, 19h29
  2. affecter un champs a une variable!
    Par Alabama-song dans le forum Requêtes
    Réponses: 3
    Dernier message: 09/11/2007, 12h58
  3. Récupération d'un champ dans une variable
    Par manu971 dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 08/11/2007, 14h47
  4. Réponses: 3
    Dernier message: 09/10/2007, 14h24
  5. Affecter valeur d'un champ dans une variable
    Par Sly2k dans le forum Access
    Réponses: 3
    Dernier message: 17/08/2006, 09h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo