Question

J'écris un moteur de blog très simple pour son usage personnel (car chaque moteur de blog que j'ai rencontré est trop complexe). Je souhaite pouvoir identifier chaque publication de manière unique par son URL, qui ressemble à / 2009/03/05 / my-blog-post-slug . Pour accomplir cela dans la couche de données, je veux créer une contrainte unique composée sur (Date, Nom), Date est uniquement la partie date (en ignorant l'heure du jour). de la date de composition. J'ai moi-même quelques idées (comme une autre colonne, probablement calculée, pour ne conserver que la partie date) mais je suis venu à SO pour savoir quelle est la meilleure pratique pour résoudre ce problème.

Je doute que la version de SQL Server soit importante ici, mais pour les enregistrements, je suis sur 2008 Express (j'apprécie une solution plus portable).

Schéma de table:

create table Entries (
    Identifier int not null identity,
    CompositionDate datetime not null default getdate(),
    Slug varchar(128) not null default '',
    Title nvarchar(max) not null default '',
    ShortBody nvarchar(max) not null default '',
    Body nvarchar(max) not null default '',
    FeedbackState tinyint not null default 0,
    constraint pk_Entries primary key(Identifier),

    constraint uk_Entries unique (Date, Slug) -- the subject of the question
)

Solution sélectionnée:

Je pense que la solution de marc est plus appropriée, étant donné que cette question concerne environ 2008. Toutefois, je vais utiliser la méthode des nombres entiers (mais pas avec les INSERT , car elle ne garantit pas l'intégrité Je vais utiliser une colonne d’entiers précalculée car je pense qu’il est plus facile de travailler avec l’entier du client (dans la requête).

Merci les gars.

create table Entries (
    Identifier int not null identity,
    CompositionDate smalldatetime not null default getdate(),
    CompositionDateStamp as cast(year(CompositionDate) * 10000 + month(CompositionDate) * 100 + day(CompositionDate) as int) persisted,
    Slug varchar(128) not null default '',
    Title nvarchar(max) not null default '',
    ShortBody nvarchar(max) not null default '',
    Body nvarchar(max) not null default '',
    FeedbackState tinyint not null default 0,
    constraint pk_Entries primary key(Identifier),
    constraint uk_Entries unique (CompositionDateStamp, Slug)
)
go
Était-ce utile?

La solution

Dans SQL Server 2008, il existe un nouveau type de données appelé "DATE". - vous pouvez utiliser cette colonne et créer un index à ce sujet.

Vous pouvez bien sûr aussi ajouter une colonne calculée du type "DATE". dans votre table et remplissez simplement la partie date de la colonne DATETIME dans cette colonne calculée, rendez-la PERSISTED et indexez-la. Devrait bien fonctionner!

Quelque chose comme ça:

ALTER TABLE dbo.Entries
   ADD DateOnly as CAST(CompositionDate AS DATE) PERSISTED

CREATE UNIQUE INDEX UX_Entries ON Entries(DateOnly, Slug)

Marc

Autres conseils

Puisque vous êtes sur 2008, utilisez le type de données Date comme le suggère Marc. Sinon, une solution plus simple consiste à avoir une colonne non calculée (ce qui signifie que vous devrez la renseigner sur un INSERT) qui utilise la date au format AAAAMMJJ. C'est un type de données entier, petit et facile à utiliser.

Pour SQL 2005, vous pouvez faire essentiellement la même chose que celle recommandée par marc: utilisez simplement un DateTime standard. Cela ressemblerait à quelque chose comme ça (code non testé ici):

ALTER TABLE Entries ADD
    JustTheDate AS DATEADD(day, DATEDIFF(day, 0, CompositionDate), 0) NOT NULL PERSISTED

Créez ensuite votre index sur (JustTheDate, Slug)

Remarque: l’instruction DATEADD / DATEDIFF ne calcule que la date de CompositionDate.

Au fil des années, nous avons eu divers problèmes avec les colonnes calculées dans SQL Server. Nous avons donc cessé de les utiliser.

Vous pouvez utiliser une vue avec une colonne pour la date uniquement et mettre un index unique sur la colonne de cette vue.

(Un effet secondaire éventuellement utile est que vous pouvez faire en sorte que VIEW exclue certaines lignes. Ainsi, vous pouvez implémenter des éléments tels que " DateColumn doit être unique, mais exclure WHERE DateColumn IS NULL)

La colonne CompositionDate existante peut être scindée en deux champs - CompositionDate et CompositionTime - et une vue de récupération qui les associe si vous en avez besoin - ce qui autoriserait alors un index natif dans la colonne de date uniquement

(Ceci peut être implémenté dans SQL 2005 et versions antérieures à l'aide de DateTime - bien que légèrement extravagant pour la date ou l'heure, et non les deux)

Enfin, un déclencheur INSERT / UPDATE pourrait indiquer qu’aucun autre enregistrement n’existait avec un doublon CompositionDate (partie de date uniquement)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top