web-dev-qa-db-fra.com

Quels caractères sont valides dans un nom de base de données SQL Server?

Nous allons fournir à nos clients un outil qui (entre autres) crée une nouvelle base de données SQL Server, et je veux pouvoir faire une validation de base sur le nom de la base de données qu'ils fournissent. La documentation de SQL Server explique quels caractères sont valides dans un nom de base de données. Cependant, la documentation est apparemment incorrecte, car je peux créer avec succès des bases de données dont les noms violent les règles documentées.

Selon la documentation de SQL Server pour CREATE DATABASE , les noms de base de données doivent respecter les règles relatives aux identificateurs; et les règles pour identificateurs dépendent du niveau de compatibilité de la base de données. Lorsque le niveau de compatibilité est 100 (ce qui, selon SQL Server Management Studio, signifie "SQL Server 2008"), le nom doit commencer par une lettre Unicode, _, @, ou #; suivi d'une ou plusieurs lettres, chiffres, @, $, #, ou _. La documentation indique clairement que les espaces intégrés ou les caractères spéciaux ne sont pas autorisés.

Cela va à l'encontre des preuves disponibles, car je peux utiliser SQL Server Management Studio pour créer une base de données dont le nom est This & That | "Other" - qui contient non seulement des espaces intégrés (explicitement interdits), mais contient des caractères spéciaux (|, ") qui ne sont même pas valides dans un nom de fichier. J'ai vérifié et le niveau de compatibilité de la base de données est bien "SQL Server 2008 (100)", même si son nom est invalide à ce niveau de compatibilité.

Heck, je peux même faire CREATE DATABASE " " (oui, c'est un seul espace), ce qui prouve que le premier caractère pas doit être une lettre, un trait de soulignement, un signe ou un signe dièse.

Donc je suppose que ma question est, quels caractères sont valides dans un nom de base de données SQL Server? Existe-t-il des règles documentées qui sont cohérentes avec le comportement réel de SQL Server?

48
Joe White

L'état règles pour les identifiants à la fin:

Lorsque des identificateurs sont utilisés dans des instructions Transact-SQL, les identificateurs qui ne respectent pas ces règles doivent être délimités par des guillemets doubles ou des crochets.

En choisissant un nom de base de données qui n'est pas conforme à ces règles, vous devez le mettre toujours entre guillemets doubles ou crochets.

Si les règles pour les identifiants réguliers sont respectées, vous pouvez utiliser le nom de votre base de données sans guillemets/crochets.

Les instructions suivantes sont correctes

CREATE DATABASE [conformingName]
CREATE DATABASE conformingName
CREATE DATABASE [This & That | "Other"]

mais non

CREATE DATABASE This & That | "Other"

MODIFIER:

Je suis d'accord que ce n'est pas ainsi que l'on comprendrait la documentation liée: qu'est-ce que doit respecter les règles pour les identifiants signifie si les règles ne s'appliquent plus comme dès que l'identifiant est joint? Le point sur la mise en cache des identifiants non conformes devrait faire partie des règles.

28
marapet

Il existe une différence entre les identifiants réguliers et les identifiants délimités. Un identifiant régulier est lié par les limitations que vous mentionnez, tandis qu'un identifiant délimité peut contenir n'importe quel caractère (sauf le délimiteur).

Comme vous utilisez des guillemets autour de l'identifiant, c'est un identifiant délimité et vous n'êtes pas limité par les règles des identifiants réguliers.

Sans les délimiteurs, vous ne pouvez créer que des bases de données avec des identifiants qui suivent les règles des identifiants réguliers:

create database db_name

Avec les délimiteurs, vous pouvez utiliser à peu près n'importe quoi:

create database "That's a funny name, isn't it?"

create database [)(/%Q)/#&%¤)Q/#)!]
10
Guffa

Personnellement, je les limiterais à l'alphabet et aux chiffres et rien d'autre (enfin peut-être aussi un _). Pas d'espaces, pas de symboles amusants, pas de retour de chariot, etc. C'est le plus sûr que vous puissiez faire.

7
HLGEM

Les noms délimités - entourés de crochets ou de guillemets doubles (si QUOTED_IDENTIFIER est défini sur ON) - peuvent contenir essentiellement autre chose que les délimiteurs eux-mêmes. Il est même possible d'utiliser les délimiteurs dans le nom avec une logique d'échappement. Notez cependant que seul le caractère d'échappement de fermeture doit être échappé. Dans le premier exemple ci-dessous, l'instance unique du caractère d'échappement d'ouverture dans le nom n'a pas besoin d'être échappée tandis que le caractère d'échappement de fermeture doit être échappé (en remplaçant l'instance unique par deux). Je suppose que la logique ici est que le code qui analyse ces instructions recherche un caractère d'échappement de fermeture et ne s'intéresse pas aux caractères d'échappement d'ouverture imbriqués.

  • [Test [Test] -> Test [Test
  • [Test]] Test] -> Test] Test

Ce qui suit est une description des règles entourant les noms d'identificateurs non délimités (non entre guillemets) dans SQL Server 2012. Il s'agit d'un extrait du document Guide de migration de MySQL vers SQL Server 2012 .

Noms des objets de schéma

Dans SQL Server 2012, un nom d'objet peut contenir jusqu'à 128 caractères.

Les noms d'identificateurs non cités doivent suivre ces règles:

  • Le premier caractère doit être alphanumérique, un trait de soulignement (_), un signe at (@) ou un signe numérique (#).
  • Les caractères suivants peuvent inclure des caractères alphanumériques, un trait de soulignement, un signe at (@), un signe numérique ou un signe dollar.
  • L'identifiant ne doit pas être un mot réservé Transact-SQL. Guide de migration de MySQL vers SQL Server 2012 8
  • Les espaces intégrés ou les caractères spéciaux ne sont pas autorisés.

Les identificateurs qui commencent par @ ou un signe numérique ont des significations spéciales. Les identificateurs commençant par @ sont des noms de variables locales. Ceux qui commencent par un signe numérique sont des noms de table temporaires.

Pour citer un nom d'identifiant dans Transact-SQL, vous devez utiliser des crochets ([]).

4
Scott Munro