Le conflit de noms avec la vue système sys.sysusers dans SQL Server

(Notez que c'était sur SQL Server 2008, mais j'ai un collègue qui signale le même problème sur SQL Server 2014.)

J'utilise un framework qui supporte plusieurs back-ends de bases de données, et notre application a une table appelée sysUsers , qui fonctionne bien dans MySQL.

Nous devons maintenant l'installer sur SQLServer et il semble que ce nom soit en conflit avec une vue système embeddede. La vue système est sys.sysusers et la table d'application est dbo.sysUsers .

Je suis conscient que la différence de cas n'est pas pertinente pour SQL Server, mais le schéma semble être ignoré pour une raison quelconque.

  • SELECT * FROM sys.sysusers; returnne les loggings de sys.sysusers . C'est entièrement comme prévu.
  • SELECT * FROM sysUsers; returnne les loggings de sys.sysusers . C'est surprenant (j'aurais pensé que le schéma local aurait préséance) mais peut-être explicable.
  • Cependant, SELECT * FROM dbo.sysUsers; renvoie toujours les loggings de sys.sysusers . Cela semble tout simplement faux car je sélectionne explicitement le schéma dbo .

Je n'ai rien trouvé dans la documentation MS qui dit que ces noms sont réservés.

J'ai essayé de renommer la table et de pirater le code pour utiliser un nom différent, et tout fonctionne (ce qui n'a rien à voir avec l'intégration SQLServer dans l'application) et les mêmes résultats sont visibles lors de l'exécution des requêtes depuis la console de gestion. Par conséquent, cela semble définitivement être un problème avec le nom de la table en conflit et non une erreur de middleware ou une différence de syntaxe.

Si ce nom de table est réservé, pourquoi MSSMS me permet-il de le créer? Si ce n'est pas réservé, pourquoi ne me laisse-t-il pas l'interroger?

Et comment puis-je contourner le problème sans nécessiter de mises à jour d'applications (car ce serait un casse-tête de migration pour d'autres deployments).

Il y a au less trois solutions de contournement, mais aucune ne garantit qu'aucun code ne doit être réécrit (sauf celui qui est horriblement dangereux):

  • Utilisez un classment sensible à la casse lors de la création de votre database ( CREATE DATABASE Foo COLLATE Latin1_General_CS_AS ). Dans ce cas, sysUsers sera un object différent de sysusers , en toutes circonstances. Vous pouvez définir un classment insensible à la casse immédiatement après la création de la database afin que vos données ne soient pas sensibles à la casse, car ce n'est probablement pas ce que souhaitent les users finaux. Évidemment, cela ne fonctionnera pas si votre application s'appuie réellement sur des noms d'objects insensibles à la casse, sauf si vous réécrivez vos requêtes avec soin. Notez que cela signifie que tous les objects de database, même ceux créés par la suite, auront des noms sensibles à la casse, car ceux-ci sont embeddeds dans les tables système à la création et ne peuvent pas être modifiés par la suite.
  • Utilisez un schéma autre que dbo . Le mappage de la table système se produit uniquement pour ce schéma, pas pour les autres. Si votre application utilise exclusivement son propre schéma, les sysusers vous créez ne seront pas sys.sysusers à sys.sysusers . Notez que pour que cela fonctionne, vous devez toujours spécifier explicitement le schéma même s'il s'agit du schéma par défaut pour votre user, sinon vous obtiendrez à nouveau le système. table (je considérerais cela comme un bug, mais c'est probablement une nécessité à cause de la façon dont les anciens scripts supposent que les sysusers résolvent n'importe où).
  • Activez la connection Dedicated Administrator , redémarrez SQL Server en mode mono-user, basculez la database READ_WRITE vers READ_WRITE et DROP VIEW sysusers . Cela supprimera sys.sysusers de toutes les bases de données. Cela annulera votre garantie, le Support Microsoft se moquera de vous si vous venez en pleurant, cela peut rendre impossible l'installation de futurs Service Packs et mises à jour et ce n'est pas recommandé , mais je le mentionne quand même, pour la science. Aucun code ne devrait utiliser cette vue, mais, vous savez, je ne suis pas un ingénieur travaillant sur SQL Server lui-même.

Notez que l'abaissement du niveau de compatibilité n'est pas une solution de contournement, que je mentionne pour l'exhaustivité. Cela n'a aucun effet sur la façon dont ces noms de tables sont résolus, même si c'était une approche souhaitable (ce qui n'est pas le cas).

Je considère la modification faite dans SQL Server 2012 pour ignorer le qualificateur dbo et résoudre à ces vieux noms obsolètes de toute façon une erreur et si cela ne tenait qu'à moi, je permettrait au less de désactiver ce comportement avec un indicateur de trace mais ce n'est pas à moi de décider. Vous pouvez envisager d'ouvrir un problème sur Microsoft Connect pour cela, car le comportement actuel le rend inutilement compliqué pour que le code indépendant du SGBDR puisse s'exécuter.