Cet article est le premier d'une série sur les principes fondamentaux des expressions de table dans T-SQL. Je me concentrerai principalement sur quatre types d'expressions de table nommées, connues dans T-SQL sous le nom de tables dérivées, d'expressions de table communes (CTE), de vues et de fonctions de table en ligne (TVF en ligne).
J'ai été inspiré pour écrire cette série par mon bon ami, Grant Fritchey, que je connais depuis de nombreuses années. Comme le souligne à plusieurs reprises Grant, beaucoup de ceux qui utilisent des expressions de table courantes dans T-SQL pensent que SQL Server persiste dans le jeu de résultats de la requête interne et que la raison de cette croyance est l'utilisation du terme table dans le nom de la construction. Lorsque ce sujet est abordé dans les discussions de la communauté, les gens soutiennent souvent que l'utilisation du terme table dans le nom de la construction est inappropriée car ce n'est pas vraiment une table. Il y a même des suggestions pour lancer une campagne de nommage dans l'espoir de voir un futur changement de nom pour cette construction, au moins dans T-SQL. Certaines des suggestions incluent expression de requête , vue intégrée , vue au niveau de l'instruction , et d'autres.
Cela surprendra peut-être certains, mais je trouve en fait l'utilisation du terme table dans l'expression de table commune comme très approprié. En fait, je trouve l'utilisation du terme expression de table le cas échéant. Pour moi, la meilleure façon de décrire ce qu'est un CTE dans T-SQL, c'est une expression de table nommée . Il en va de même pour ce que T-SQL appelle les tables dérivées (la construction de langage spécifique par opposition à l'idée générale), les vues et les TVF en ligne. Ce sont toutes des expressions de table nommées.
Si vous pouvez me supporter un peu, je vais fournir le raisonnement de ma vision des choses dans cet article. Il m'est venu à l'esprit que la confusion des noms et la confusion quant à savoir s'il existe un aspect de persistance dans les expressions de table peuvent être résolues grâce à une meilleure compréhension des principes fondamentaux de notre domaine des systèmes de gestion de bases de données relationnelles. Ces principes fondamentaux étant la théorie relationnelle, la relation entre SQL (le langage standard) et la relation entre le dialecte T-SQL utilisé dans les implémentations SQL Server et Azure SQL Database.
Pour commencer, vous souhaitez être en mesure de répondre aux questions suivantes :
- Qu'est-ce que l'indépendance physique des données principe dans le modèle relationnel signifie?
- Qu'est-ce qu'une table en SQL et quelle est sa contrepartie dans le modèle relationnel ?
- Quelle est la propriété de clôture de l'algèbre relationnelle ?
- Qu'est-ce qu'une expression de table et quelle est sa contrepartie dans le modèle relationnel ?
Une fois que vous serez en mesure de répondre correctement aux questions ci-dessus, vous trouverez très probablement l'utilisation du terme expression de table nommée le cas échéant pour les constructions susmentionnées (ce que T-SQL appelle des tables dérivées, des CTE, des vues et des TVF en ligne).
Je ne veux pas donner l'impression que j'ai une compréhension très profonde de la théorie relationnelle. Mon expertise est T-SQL. Je reconnais qu'il y a beaucoup plus que je ne sais pas sur la théorie relationnelle que moi, et que certaines choses que je pense savoir, ne le sont tout simplement pas. Quand je lis les écrits de C. J. Dates sur le sujet, j'ai l'impression d'effleurer à peine la surface de ce qu'il y a à savoir, et que je pourrais, et devrais, m'efforcer de mieux le comprendre. Je reconnais et je crois fermement qu'une bonne compréhension de la théorie relationnelle se traduit directement par une meilleure compréhension de SQL et de T-SQL, et par l'écriture d'un code T-SQL meilleur, plus précis et plus robuste. Pour tous ceux qui choisissent les données comme carrière, je recommande de lire SQL and Relational Theory:How to Write Accurate SQL Code 3rd Edition par C. J. Date (O'Reilly 2015).
Dans la première partie de cette série, je souhaite établir une compréhension de mon utilisation des termes expression de table et expression de table nommée , ce qui est en accord avec l'utilisation de ce terme par Date, et malheureusement pas en accord avec l'utilisation de ce terme par la norme SQL. Pour y parvenir, je fournirai un peu de contexte de la théorie relationnelle et de la norme SQL. Mais comme je l'ai dit, je recommande de lire le livre de Date pour une couverture vraiment détaillée de ce sujet.
Je commencerai par expliquer ce que signifie le principe d'indépendance des données physiques. Ensuite, j'expliquerai ce qu'est une table en SQL et son homologue en théorie relationnelle. J'expliquerai ensuite ce que signifie la propriété de clôture de l'algèbre relationnelle. Une fois que vous avez une idée raisonnable de ce qu'est une table et de ce que signifie la propriété de fermeture, il devient assez simple de comprendre ce qu'est une expression de table. Je me concentrerai ensuite sur les spécificités de T-SQL. J'ai beaucoup à dire sur les principes fondamentaux des expressions de table dans T-SQL, à la fois en termes de traitement conceptuel et en termes de détails d'implémentation, y compris la représentation physique et les considérations de réglage des requêtes.
Je trouve ce sujet fascinant et très pratique une fois que vous avez approfondi les détails de la mise en œuvre. En fait, j'ai tellement de choses à dire à ce sujet que je ne sais pas combien de parties cette série comportera éventuellement. Ce que je peux vous dire avec une grande confiance, c'est qu'il y aura plusieurs parties. Probablement plus d'une et moins de 100. Dans les prochaines parties, j'approfondirai les types individuels d'expressions de table nommées, les considérations de modification, les aspects d'inline, les aspects d'ordre, les corrélations, et plus encore.
Dans mes exemples, j'utiliserai un exemple de base de données appelé TSQLV5. Vous pouvez trouver le script qui crée et remplit cette base de données ici, et son diagramme ER ici.
Indépendance des données physiques
L'indépendance des données physiques est un principe de la théorie relationnelle selon lequel les détails de l'implémentation physique doivent être cachés ou transparents pour l'utilisateur soumettant les requêtes au système de gestion de base de données relationnelle. Dans les requêtes, les utilisateurs sont censés se concentrer sur quoi ils ont besoin d'utiliser des opérations logiques basées sur l'algèbre relationnelle, par opposition à comment pour obtenir les données. Ils ne sont pas censés s'inquiéter de la façon dont les données sont structurées, consultées et traitées. Ces détails d'implémentation physique ont tendance à différer considérablement entre les différentes implémentations (produits RDBMS). Même avec le même RDBMS, les détails d'implémentation physique changent parfois entre différentes versions et builds. L'idée derrière le principe d'indépendance des données physiques est en théorie de protéger l'investissement de l'utilisateur en supprimant la nécessité de réviser vos solutions lorsque vous mettez à niveau votre SGBDR vers une nouvelle version, ou même lorsque vous migrez d'un SGBDR à un autre. Comme vous le savez probablement bien, dans la pratique, les choses ne sont pas si simples, mais c'est un sujet de discussion différent.
Qu'est-ce qu'un tableau ?
Si vous travaillez avec T-SQL ou tout autre dialecte de SQL depuis un certain temps, vous développez une compréhension intuitive de ce qu'est une table. Le problème est que sans une certaine connaissance de la théorie relationnelle, la compréhension intuitive n'est souvent pas très précise. Une erreur typique est que nous avons intuitivement tendance à nous concentrer sur les détails de la mise en œuvre physique. Par exemple, lorsque vous réfléchissez à ce qu'est une table, pensez-vous à une table comme une structure logique (un ensemble de lignes) ou pensez-vous aux détails d'implémentation physique dans la plate-forme que vous utilisez (dans SQL Server , pages, étendues, tas versus index clusterisé, index non clusterisés, etc.) ? En tant qu'utilisateur écrivant du code SQL pour interroger une table, en suivant le principe d'indépendance des données physiques, vous êtes censé considérer la table comme une structure logique et laisser le SGBDR s'occuper des détails d'implémentation physique. Alors, prenons du recul et essayons de comprendre ce qu'est une table.
Une table est la contrepartie de SQL à la structure principale de la théorie relationnelle - une relation. Pour garder les choses simples et limiter la portée de ma couverture, je ne vais pas entrer dans la distinction entre une variable de relation et une valeur de relation. Si vous suivez ma recommandation et lisez le livre de Date, vous aurez très vite une image claire de ces subtilités.
Une relation a un titre et un corps.
L'en-tête de la relation est un ensemble des attributs . Dans la théorie mathématique des ensembles, un ensemble n'a ni ordre ni doublons. Vous êtes censé identifier un attribut par son nom et non par une position. Par conséquent, les noms d'attribut doivent être uniques.
Pouvez-vous identifier quelle est la contrepartie d'un attribut en SQL ? Vous avez probablement deviné qu'il s'agit d'une colonne . Cependant, SQL a en fait une notion d'ordre dans ses colonnes en fonction de leur ordre d'apparition dans l'instruction CREATE TABLE. Par exemple, voici l'instruction CREATE TABLE pour la table Sales.Shippers dans la base de données TSQLV5 :
CREATE TABLE Sales.Shippers ( shipperid INT NOT NULL IDENTITY, companyname NVARCHAR(40) NOT NULL, phone NVARCHAR(24) NOT NULL, CONSTRAINT PK_Shippers PRIMARY KEY(shipperid) );
Interrogez la table en utilisant le fameux SELECT *
, comme ceci :
SELECT * FROM Sales.Shippers;
Lorsque j'ai exécuté cette requête dans mon système, j'ai obtenu le résultat suivant :
shipperid companyname phone ---------- -------------- --------------- 1 Shipper GVSUA (503) 555-0137 2 Shipper ETYNR (425) 555-0136 3 Shipper ZHISN (415) 555-0138
SQL garantit que les colonnes seront renvoyées de gauche à droite en fonction de l'ordre de définition. Je vais vous expliquer ce qui se passe avec les rangées sous peu. SQL vous permet même de faire référence à la position ordinale de la colonne de la liste SELECT dans la clause ORDER BY, comme ceci (pas que je recommande cette pratique, pas plus qu'Aaron Bertrand) :
SELECT shipperid, companyname, phone FROM Sales.Shippers ORDER BY 2;
Cette requête génère la sortie suivante :
shipperid companyname phone ---------- -------------- --------------- 2 Shipper ETYNR (425) 555-0136 1 Shipper GVSUA (503) 555-0137 3 Shipper ZHISN (415) 555-0138
Le corps d'une relation est un ensemble de tuples . Encore une fois, rappelez-vous qu'un ensemble n'a pas d'ordre et pas de doublons. Par conséquent, une relation doit avoir au moins une clé candidate qui vous permet d'identifier de manière unique un tuple. L'équivalent SQL d'un tuple est une ligne . Cependant, en SQL, vous n'êtes pas obligé de définir une clé dans une table, et si vous ne le faites pas, vous pouvez vous retrouver avec des lignes en double. Même si vous avez une clé définie dans votre table, vous pouvez obtenir des lignes en double renvoyées par une requête sur la table. Voici un exemple :
SELECT country FROM HR.Employees;
Cette requête génère la sortie suivante :
country -------- USA USA USA USA UK UK UK USA UK
Cette requête ne produit pas de résultat relationnel en raison de la possibilité de lignes en double. Alors que la théorie relationnelle est basée sur la théorie des ensembles, SQL est basé sur la théorie des multi-ensembles. Un multiset (c'est-à-dire un sur-ensemble ou un sac) peut avoir des doublons. SQL vous donne un outil pour éliminer les doublons avec une clause DISTINCT, comme ceci :
SELECT DISTINCT country FROM HR.Employees;
Cette requête génère la sortie suivante :
country -------- UK USA
Ce que SQL maintient de la théorie relationnelle en termes de corps de table est la propriété de non-ordre. À moins que vous n'ajoutiez une clause ORDER BY dans la requête, vous n'avez aucune garantie que le résultat aura un ordre spécifique parmi les lignes. Ainsi, le corps du résultat de la requête ci-dessus est relationnel, du moins en ce sens qu'il n'a pas de doublons et qu'il n'a pas d'ordre garanti.
Supposons que vous interrogez une table dans SQL Server et que vous n'incluez pas de clause ORDER BY dans la requête. Vous attendez-vous à ce que SQL Server renvoie toujours les lignes dans un ordre spécifique comme comportement garanti ? Beaucoup de gens le font. Beaucoup pensent que vous récupérerez toujours les lignes en fonction de l'ordre de l'index clusterisé. C'est un bon exemple d'ignorer le principe d'indépendance des données physiques et de faire des hypothèses basées sur l'intuition, et peut-être sur le comportement observé dans le passé. Microsoft sait qu'une requête SQL sans clause ORDER BY ne garantit aucun ordre parmi les lignes de résultat, et donc même si au niveau physique les données résident dans une structure d'index, SQL Server n'a pas à traiter les données dans index Commande. Il peut choisir, dans certaines conditions physiques, de le faire, mais il peut choisir de ne pas le faire dans d'autres conditions physiques. Rappelez-vous également que les détails d'implémentation physique peuvent changer entre les différentes versions et builds du produit. Si vous voulez garantir que la requête renverra les lignes de résultats dans un ordre spécifique, votre seul moyen de le garantir est d'introduire une clause ORDER BY dans la requête la plus externe.
Comme vous l'avez probablement compris, les concepteurs de SQL n'ont pas vraiment considéré comme une priorité de suivre la théorie relationnelle. Et ce que j'ai décrit ici ne sont que quelques exemples. Il y en a beaucoup plus. Comme mentionné précédemment, mon objectif dans cet article est simplement de fournir suffisamment de connaissances théoriques essentielles pour dissiper la confusion entourant les expressions de table, avant de commencer à approfondir les spécificités de T-SQL dans de futurs articles.
Qu'est-ce qu'une expression de tableau ?
L'algèbre relationnelle (l'algèbre qui définit les opérations sur les relations dans la théorie relationnelle) a une fermeture biens. Cela signifie qu'une opération sur des relations produit une relation. Un opérateur relationnel opère sur une ou plusieurs relations en entrée et produit une seule relation en sortie. La propriété de fermeture vous permet d'imbriquer des opérations. Une expression relationnelle est une expression qui opère sur des relations et renvoie une relation. Une expression relationnelle peut donc être utilisée là où l'algèbre relationnelle attend une relation.
Si vous y réfléchissez, ce n'est pas différent des opérations sur des nombres entiers qui donnent un résultat entier. Supposons que la variable @i est une variable entière. L'expression @i + 42 donne un entier et peut donc être utilisée là où un entier est attendu, comme dans (@i + 42) * 2.
Étant donné qu'une table en SQL est la contrepartie d'une relation dans la théorie relationnelle, même si elle n'est pas très réussie, une expression de table en SQL est la contrepartie d'une expression relationnelle. Comme mentionné précédemment, j'utilise le terme expression de table après l'utilisation de ce terme par C. J. Dates. La norme SQL contient une multitude de termes déroutants, dont certains, je le crains, ne sont pas très appropriés. Par exemple, le standard SQL utilise le terme expression de table pour décrire spécifiquement une expression basée sur les clauses de requête commençant par une clause FROM obligatoire, et incluant éventuellement les clauses WHERE, GROUP BY, HAVING et WINDOW (la dernière n'est pas prise en charge dans T -SQL), et en excluant la clause SELECT. Voici les spécifications de la norme :
7.4
Fonction
Spécifier un tableau ou un tableau groupé.
Formater