Primary key de type char/varchar [SQL SERVER] - SQL/NoSQL - Programmation
Marsh Posté le 24-02-2005 à 16:36:03
en CHAR ça doit fonctionné, c'est clair qu'en VARCHAR c'est peut probable que ça marche...
c'est pas intelligent de distingué deux tuples rien qu'avec un espace...
a la limite, c'est peut etre mieux de mettre un nombre derriere alors
ex:
FOURNISSEUR1
FOURNISSEUR2
mais pas d'espace, évite ça
Marsh Posté le 24-02-2005 à 16:41:16
moi23372 a écrit : en CHAR ça doit fonctionné, c'est clair qu'en VARCHAR c'est peut probable que ça marche... |
Le monsieur te dit que c'est déjà comme ça et qu'il a des données à récupérer, il te demande pas comment il aurait fallu faire pour que ça arrive pas...
Marsh Posté le 24-02-2005 à 16:48:25
Tu remplaces la primary key foireuse par un vrai ID
(bon évidemment ça va faire plus de boulot mais ça sera beaucoup moins laid)
Marsh Posté le 24-02-2005 à 16:54:51
skeye a écrit : Le monsieur te dit que c'est déjà comme ça et qu'il a des données à récupérer, il te demande pas comment il aurait fallu faire pour que ça arrive pas... |
Effectivement j'ai pas trop le choix
Et surtout que remplacer le varchar par un char, ben c'est carrément pas la bonne idée
Vu que mon 'fournisseur', en char de 20 par exemple, va être stocké comme un 'fournisseur '.
Bon, sinon j'avais bien une solution, qui est de stocker aussi la longueur du champ dans la base, et faire une clé primaire sur le champ varchar + la longueur de la clé.
Le coup de l'ID, c'est à voir aussi.
En fait j'voulais savoir s'il y avait une solution 'normale' (parce que pour moi c'est SQL SERVER qui chie un peu là) vu que mon chef d'équipe revient pas avant demain après midi
Bref, merci pour vos réponses
Marsh Posté le 24-02-2005 à 19:34:20
skeye a écrit : Le monsieur te dit que c'est déjà comme ça et qu'il a des données à récupérer, il te demande pas comment il aurait fallu faire pour que ça arrive pas... |
je sais bien ce qu'il a dit, mais s'il ne veut pas que posposer le problème, autant faire ça convenablement, désolé mais c'est pas si compliqué que ça, suffit d'écrire une petite procédure pour cela...
Marsh Posté le 24-02-2005 à 19:38:58
moi23372 a écrit : je sais bien ce qu'il a dit, mais s'il ne veut pas que posposer le problème, autant faire ça convenablement, désolé mais c'est pas si compliqué que ça, suffit d'écrire une petite procédure pour cela... |
Convenablement? Tu devrais vite effacer ton premier post parce que ta solution est loin d'être convenable! C'est une réponse de débutant!
Marsh Posté le 24-02-2005 à 20:14:23
si tu le dis ;-)
néanmoins, jusqu'a présent, il n'y a que moi qui ai proposé un début de solution, tandis que toi, a part spamer le forum, tu ne fais rien...
Marsh Posté le 24-02-2005 à 20:43:23
moi23372 a écrit : a part spamer le forum |
Marsh Posté le 24-02-2005 à 20:45:10
toi aussi la faute te choque ?
Marsh Posté le 24-02-2005 à 20:45:30
non, mais je vois pas le rapport avec le spam
Marsh Posté le 24-02-2005 à 21:05:46
antp a écrit : non, mais je vois pas le rapport avec le spam |
'tain vous voyez bien comment il maîtrise son sujet depuis sa première intervention sur le forum
Marsh Posté le 24-02-2005 à 21:41:06
drasche a écrit : Tu remplaces la primary key foireuse par un vrai ID |
+1
moi23372 a écrit : si tu le dis ;-) |
-1, tu sors.
Marsh Posté le 25-02-2005 à 10:09:44
chrisbk a écrit : Oué c'est le far west ici |
(on est pas tous en charente, hein...:o)
Marsh Posté le 25-02-2005 à 10:14:39
ReplyMarsh Posté le 07-03-2005 à 10:34:22
Euh...
La solution de moi23372 est loin d'être sexy (et la première tout du moins ne marche pas de toute façon), mais elle est néanmoins une meilleure piste que la réponse de Drasche.
Je travaille actuellement dans une base de données, avec pas mal de conneries dedans.
1) Aucune clé primaire sur des char/varchar. La raison évoquée est "c'est plus rapide", ce qui est absolument faut (selon les SGBD, ca peut même être parfois le contraire !)
2) Demandes débiles, du genre "ha ben faut shooter cette clé composée pour le changer en clé simple", parceque c'est lent. A nouveau, c'est faux. Force est de constater que beaucoup de gens n'ont pas compris ce qu'est un index. Par contre, vous vous êtes déjà amusé à modifier 50 tables afin d'en changer les PK et FK ? Moi oui, et c'est pour cette raison que la solution de Drasche est à mettre à la poubelle illico presto. C'est le meilleur moyen de planter totalement la base, en oubliant un champ quelque part, ou planter l'application, en oubliant une requête dans un coin.
Bref, changer de VARCHAR à CHAR, c'est pas la solution rêvée, mais ça reste une excellente solution. Par contre, il reste un problème :
"FOURNISSEUR " => "FOURNISSEUR "
"FOURNISSEUR" => "FOURNISSEUR "
=> Les deux valeurs sont à nouveau égales.
A ce moment, reste la soltution brutale de faire, avant la conversion, un "REPLACE(champ, ' ', '_')" sur la clé. Si les paramètres SQL Server sont corrects, le cascade va se déclencher, et donc mettre à jour les fils sans problème. La solution sera alors résolue tout simplement, sans changer ni le type, ni les valeurs de la PK (enfin, à peine changées).
Maintenant, évidement, s'il y a des "VALEUR_A_LA_CON" et "VALEUR A LA CON" dans la base, cette solution est à modifier.
Dans tous les cas, je suis très surpris que deux lignes de référence aient une clé si similaire. Ca ressemble plus à une erreur de saisie qu'autrechose. Avant de migrer, je pense qu'il serait préférable de s'assurer que les incohérences actuelles ne soient pas répliquées (une migration, c'est le moment rêvé pour remettre d'aplomb des données foireuses).
Bref, la solution de changer de PK me semble la piste "de la dernière chance", car à la fois inutile d'un point de vue performances, et lourde d'un point de vue mise en place (quand on bosse comme ici avec 12 Mo de procédures stockées, on s'amuse pas à changer une PK pour le plaisir, sauf quand le directeur informatique qui comprend rien à un SGBD - pour lui ça s'arrête au wizard "créer une table" dans Access) te l'impose.
Marsh Posté le 07-03-2005 à 10:42:12
Ajurna> ben c'est des encodages de end-users, c'est pour ça que ça a l'air foireux Donc pas vraiment surprenant
Marsh Posté le 07-03-2005 à 10:44:24
Ayant déjà traiter ce genre de problème, j'ai une bien mauvaise nouvelle à annoncer. Une solution est la création d'une moulinette afin de vérifier et transférer les informations. C'est chiant à mourir, c'est long, mais c'est le seul moyen.
Pour exemple, je me suis taper la migration des informations de la DRIRE d'Amiens (pour ceux qui connaissent DDIT), et franchement, migrer des données ou il n'y a eu aucun controle d'entrée est une vrai plaie.
Marsh Posté le 07-03-2005 à 10:57:42
C clair. Heureusement que sous SQL Server il y a DTS, ça simplifie pas mal le boulot
Marsh Posté le 07-03-2005 à 11:55:03
Merci Arjuna pour ta réponse
Mais bon, j'ai fini le truc depuis 1 semaine. J'ai, comme tu l'as dit, remit d'aplomb tout ça. Les fournisseurs avec les trailing blank sont, en fait, pas une erreur de saisie, mais plutôt un problème de moulinette du programme duquel je transfère les données.
J'ai eu aussi quelques autres surprises assez violentes, du genre des clefs primaires identiques, si si
Quoique non surprenant quand on a bossé deux ans avec Pervasive...
Citation : |
Si tu savais...
Le "master" programme dont sont tirées toutes ces aneries utilise les SGBD de façon un peu spéciale...
En gros, dans les tables, y a un champ, un blob, et tout est foutu en vrac dans ce blob.
Ensuite, grâce à une classe, remasterisée en fonction de la version du logiciel, le blob est parsé, et les valeurs lues dans le code source.
C'est donc même assez récurrent de trouver des clés primaires égales dans le logiciel. Par exemple un code produit doit être unique, mais il ne l'est pas. Et quand toi tu récupères les infos via un txt ou une api, t'en chies pour faire quelque chose de correct
Marsh Posté le 07-03-2005 à 17:02:09
Citation : 1) Aucune clé primaire sur des char/varchar. La raison évoquée est "c'est plus rapide", ce qui est absolument faut (selon les SGBD, ca peut même être parfois le contraire !) |
Sous sql server, c'est fortement deconseillé ! Et effectivement pour des raisons de rapidité. L'unicité est très importantes pour les index clusters. Un index cluster doit être petit, stable et si possible unique. Et Ils sont très conseillés pour optimiser une base sql server.
Plus ta clef est petite plus tu en auras par noeud d'index et donc moins tu auras d'entrées/sorties.
Donc un compteur d'entiers pour la clef primaire interne, et roulaize. Que tu affiches ensuite à ton client une reference en varchar avec un index non-cluster dessus, ok. Mais une clef primaire en char ou varchar : beurk !
Le jour où tu as à modifier le système de référencement de tes clients, ça sera d'autant plus simple que ta clef primaire interne ne change pas...
Marsh Posté le 07-03-2005 à 17:32:58
Le type des données n'impacte en rien l'index, puisque l'index a lui-même sa propre représentation interne sous forme d'entier (ou plus, selon la taille de la table).
Le type de données n'a donc rigoureusement aucune incidence.
Ensuite, lorsque ta table est très grande, l'index sera alors constitué en interne soit de NUMERIC soit de GUID (je pense que c'est plutôt ce second type), qui est de 80 bits, soit 10 octets, ce qui est à la fois énorme, et inadapté aux processeurs, qui ne savent faire des calculs que sur 32 ou 64 bits (et pas sur 80...)
Et même si SQL Server ne travaillait pas de la sorte, "FOURNISSEUR" ça fait 11 caractères, donc de toute façon, la différence avec un type de 80 bits est tellement faible qu'elle n'a aucun impact sur la vitesse de traîtement.
Ensuite, imagine une clé sur un CHAR(4) (c'est cette valeur ou plus petite que je préconise généralement), la représentation mémoie, c'est 4 octets, soit rigoureusement la même qu'un entier (32 bits).
Bref, une clé à base de CHAR est infiniement plus lisible, et pourtant, ne fait absoluement rien perdre à la vitesse de traîtement.
Marsh Posté le 07-03-2005 à 17:35:11
PS: montre-moi l'article que l'aide SQL Serveur où ils déconseillent l'utilisation de ce type. J'ai jamais trouvé dans SQL Server. Sous Oracle, en tout cas, sûr et certain, ça n'a rigoureusement aucune incidence, les CHAR et les entiers étant de toute façon au final gérés de la même façon dans les index (4 char, tu peux très bien en faire un int(32) et faire tes calculs dessus)
A la limite, je dis pas pour les types nchar et nvarchar, qui sont lourds à traîter, de par le fait qu'un caractère peut s'étaller de 1 à 4 byte.
Marsh Posté le 07-03-2005 à 17:57:16
Si tu parles de char(4), on est d'accord (cela dit, je ne vois pas en quoi c'est plus lisible ?), puisque cela reste un petit index.
un noeud, c'est une page de 8ko, plus ta clef est petite...plus tu en as par noeud
Ton index_cluster tu le places generalement sur ta clef primaire (petite...et unique) et comme lorsque tu vas passer par un non_cluster, il va traverser l'index cluster autant qu'il ait un minimum de noeuds à parcourir
je n'ai pas d'article à ce sujet...seulement un classeur de formation sur les bases sql server performantes
Marsh Posté le 07-03-2005 à 18:07:42
Forcément, on va pas faire une clé unique sur un nvarchar(8192) faudrait être marteau (et pkoi pas une clé composée de 128 champs de ce type pendait qu'on y est )
Sinon, pour une table de référence "type" par exemple, tu peux faire :
1 Commande
2 Proforma
3 Devis
4 etc.
Ou alors :
CDE Commande
PRF Proforma
DEV Devis
ETC Etc.
Par exemple L'intérêt d'avoir un code lisible, c'est que lorsque tu consultes ta table des évènements, t'auras pas exemple :
DEV 125 06/08/2001 897.25 Monsieur Dupond avec un D
PRF 389 16/06/1999 125.56 Monsieur Dupont avec un T
Bah entre "DEV" et "PRF", on isole vachement mieu les devis et les proforma
Marsh Posté le 07-03-2005 à 18:13:37
Et comment fais-tu pour garantir l'unicité pour ce type de clef ? Comment tu les génères ? C'est à l'utilisateur de le faire ?
Marsh Posté le 07-03-2005 à 20:02:59
ben c'est une bête clé primaire pour la table "TYPE", et une bête clé étrangère sur la table "EVENEMENT", exactement comme si c'était un type numérique. Comprend pas ta question (??)
Marsh Posté le 07-03-2005 à 20:54:31
Les clefs primaires de la table type, tu les génères comment ? A la mano ?
Cela dit j'ai utilisé ce type de clef pour mes commerciaux. Ils sont repérés par leurs initiales
Marsh Posté le 07-03-2005 à 21:28:03
Ben... Ca de déclare comme les PK sur les nombres... Comprends pas la question... Soit tu fais un script, soit dans l'éditeur de table, tu sélectionnes la ligne et tu cliques sur le clé. Vois pas de différence !
Marsh Posté le 07-03-2005 à 23:06:26
Si tu mets un nombre, tu vas probablement utiliser un compteur. Unicité sans faille. Transparence totale pour l'utilisateur qui ne verra jamais ce code.
Là, ce sont tes users qui vont choisir la clef primaire (pas le champ, le contenu du champ), il va falloir que tu assures son unicité avant la saisie dans la base. (genre pour Developpement, s'assurer que l'user ne prenne pas DEV..sinon baoum )
De plus, si un jour ton clients te dit qu'il change le libellé commande par ...order, par exemple, ta clef devient tout de suite moins lisible. Tu fais quoi ? Tu fais une mise à jour en cascade ?
Avec une clef numerique aucun soucis..
Cle(PK) Prefixe Libellé
1 CDE Commande
2 DEV Devis
...etc
Je n'affiche à l'utilisateur que le préfixe. Il ne voit jamais ma clé.
Et quand on me demande de passer le prefixe à ORD et le libellé à ORDER....aucun soucis, nul besoin de faire une maj en cascade et de verifier l'integrité
J'ai justement rencontré ce problèmes avec les initiales en PK pour mes commerciaux. Des qu'une commerciale se marie...c'est le bordel car ses initiales changent. Du coup, j'ai bricolé une moulinette pour rajouter une clef numerique.. Je t'assure que j'aurais préféré prévenir que guérir
Marsh Posté le 07-03-2005 à 23:08:02
Ouais, moi mes clés sont TOUJOURS des integer. Jamais de clé significative. Toujours un truc abstrait Parce qu'à chaque fois que j'ai eu le malheur de mettre autre chose, tôt ou tard c'était le bordel
Marsh Posté le 07-03-2005 à 23:15:48
FlorentG a écrit : Ouais, moi mes clés sont TOUJOURS des integer. Jamais de clé significative. Toujours un truc abstrait Parce qu'à chaque fois que j'ai eu le malheur de mettre autre chose, tôt ou tard c'était le bordel |
Honnêtement, après quelques déboires, je pense que c'est la meilleure façon de travailler
Si j'avais le courage, je ferais péter ces %*$" de references chantier alphanumériques..que j'ai mis en pk, il ya 5 ans
Marsh Posté le 07-03-2005 à 23:16:22
Bah ça dépends ce que tu gères. Evidement, si c'est des infos volatiles, faut passer par une clé calculée. Mais si c'est quelquechose de fixe, ça sert à rien, mise à part alourdir.
Imagine, t'as un forum. Le login est unique, tu ne peux pas en changer. Ben utiliser un auto-incrément comme clé primaire (et donc comme FK) va t'oblier à faire des jointures à toutes les sauces pour afficher l'auteur de chaque post... C'est pas très malin étant donné que tu ne veux récupérer que son login.
C'est ni plus ni moins la solution adoptée par Joce lorsqu'il a codé ce forum. Comme tu vois, il marche plutôt bien, y'a pas de problème de perf. Pourtant, en 1999 quand j'ai découvert ce forum, et que Joce, très présent à l'époque, m'a expliqué comment il avait codé le forum, j'ai cru avoir une attaque. Force est de constater que ces choix (auxquels je n'adhère pas tous, encore maintenant) n'était pas mauvais, loin de là.
Marsh Posté le 07-03-2005 à 23:24:48
Sinon, j'ai travaillé pendant des mois (deux ans en fait) sur un ERP, dont un grand nombre de clés étaient aplhanumériques. Les pays ou les monnaies par exemple, faut être buté pour ne pas reprendre les codes alphanumériques ISO, qui sont parfaitement lisibles !
Et je peux t'assurer que ces données sont loin d'être les seules alpha-numériques. Même certaines informations, telles que le numéro client, même si elles suivent, selon leur type, différentes séquences (bah ouais, t'as l'air fin avec un auto-incrément quand tu dois gérer plusieurs plages à la fois), sont en réalité des varchar(12). Ce qui est bien pratique, c'est que si un client (type "CLI" ) sera en effet numérique (avec 0 facultitatifs, à nouveau, pas terrible quand tu te bases sur un champ entier), les dépots (qui sont gérés de la même façon que les clients) sont nommé par leur nom juridique (ça change pas tous les jours).
En tout cas, cet ERP bouffe plusieurs dizaine de milliers de ligne par jour en écriture, et plus de 1000 personnes l'utilisent simultanément, et personne se s'est jamais plaint ni de sa lenteur ni du bordel dans les données.
Evidement, les écrans permettant de créer des devises ou des dépôts sont fermés aux utilisateurs... Une clé alphanumérique, tu n'en fait que pour les données de référence évidement, pour le reste, c'est une clé calculées (et rien n'empêche d'en faire une variable alphanum... Quand tu reçois un bon de commande avec marqué "CDE0158032005", ça ressemble à tout sauf à un autonumber, et pourtant, personne n'a rien tapé pour générer cette clé)
Marsh Posté le 24-02-2005 à 11:11:52
J'suis en train de faire une migration de données d'un prog qui tournait sous une base Pervasive vers une nouvelle base SQL SERVER
Le truc, c'est qu'il y a une table sous Pervasive dont la clé primaire est un varchar, et qui contient des données du genre 'FOURNISSEUR' et 'FOURNISSEUR ' (vous remarquerez le superbe espace qui fait toute la différence).
Et ça, ça passe pas sous SQL SERVER. J'ai le droit à une violation de primary key.
J'ai beau bidouiller avec les options ANSI_PADDING, les types de données char/varchar, apparemment, si ça touche une clé primaire, c'est kekette, pour le reste, ça marche.
Quelqu'un a un idée de comment que j'peux faire ?