Domanda

Sto scrivendo un motore di blog molto semplice per uso personale (poiché ogni motore di blog che ho incontrato è troppo complesso). Voglio essere in grado di identificare in modo univoco ogni post tramite il suo URL che è qualcosa come / 2009/03/05 / my-blog-post-slug . Per realizzarlo nel livello dati, voglio creare un vincolo univoco composto su (Date, Slug) dove Date è solo la parte della data (ignorando l'ora del giorno) della data di composizione. Io stesso ho alcune idee (come un'altra colonna, probabilmente calcolata, per contenere solo la parte della data) ma sono venuto a SO per sapere qual è la migliore pratica per risolvere questo problema.

Dubito che la versione di SQL Server sia importante qui, ma per la cronaca, sono su Express 2008 (apprezzo una soluzione più portatile).

Schema tabella:

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
)

Soluzione selezionata:

Penso che la soluzione di marc sia più appropriata, considerando che questa domanda riguarda il 2008. Comunque, andrò con il metodo intero (ma non con INSERT , in quanto non garantisce l'integrità di dati; userò una colonna intera pre-calcolata) poiché penso che sia più facile lavorare con la cosa intera dal client (nella query).

Grazie ragazzi.

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
È stato utile?

Soluzione

Bene, in SQL Server 2008 c'è un nuovo tipo di dati chiamato " DATE " - puoi usare quella colonna e creare un indice su di essa.

Naturalmente puoi anche aggiungere una colonna calcolata di tipo " DATA " alla tua tabella e basta riempire la parte della data della colonna DATETIME in quella colonna calcolata, renderla PERSISTENTE e indicizzarla. Dovrebbe funzionare bene!

Qualcosa del genere:

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

CREATE UNIQUE INDEX UX_Entries ON Entries(DateOnly, Slug)

Marc

Altri suggerimenti

Dato che sei sul 2008, usa il tipo di dati Date come suggerisce Marc. Altrimenti, una soluzione più semplice è avere una colonna non calcolata (il che significa che dovrai popolarla su un INSERTO) che utilizza la data nel formato AAAAMMGG. È un tipo di dati intero ed è piccolo e facile da usare.

Per SQL 2005, potresti fare essenzialmente la stessa cosa raccomandata da marc_s, basta usare un DateTime standard. Sarebbe simile a questo (codice non testato qui):

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

Quindi crea il tuo indice su (JustTheDate, Slug)

Nota: l'istruzione DATEADD / DATEDIFF lì calcola solo la data del CompositionDate.

Nel corso degli anni abbiamo avuto una varietà di problemi con le colonne calcolate in SQL Server, quindi abbiamo smesso di usarle.

Puoi utilizzare una VISTA con una colonna solo per data e inserire un indice univoco sulla colonna di quella VISTA.

(Un possibile effetto collaterale è che puoi far sì che la VISTA escluda alcune righe, quindi puoi implementare cose come " DateColumn deve essere univoco, ma escludi DOVE DateColumn È NULL)

La colonna CompositionDate esistente potrebbe essere suddivisa in due campi - CompositionDate e CompositionTime - e una vista di recupero che li unisce nuovamente se necessario, che consentirebbe quindi un indice nativo nella colonna Solo data

(Questo può essere implementato in SQL 2005 e versioni precedenti usando DateTime - anche se leggermente stravagante solo per la data o l'ora e non entrambi)

E infine potresti avere un trigger INSERT / UPDATE che impone che non esistano altri record con un CompositionDate duplicato (solo parte della data)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top