Pregunta

Estoy escribiendo un motor de blog muy simple para uso propio (ya que cada motor de blog que encontré es demasiado complejo). Quiero poder identificar de manera única cada publicación por su URL, que es algo así como / 2009/03/05 / my-blog-post-slug . Para lograrlo en el nivel de datos, quiero crear una restricción única compuesta en (Date, Slug) donde Date es solo la parte de la fecha (ignorando la hora del día) de la fecha de composición. Yo mismo tengo algunas ideas (como otra columna, probablemente calculada, para contener solo la parte de la fecha) pero llegué a SO para saber cuál es la mejor práctica para resolver este problema.

Dudo que la versión de SQL Server sea importante aquí, pero para los registros, estoy en 2008 Express (aprecio una solución más portátil).

Esquema de tabla:

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
)

Solución seleccionada:

Creo que la solución de marc es más adecuada, ya que esta pregunta es sobre 2008. Sin embargo, usaré el método de enteros (pero no con INSERT s, ya que no garantiza la integridad de datos; usaré una columna de enteros precomputados) ya que creo que es más fácil trabajar con la cosa de enteros desde el cliente (en la consulta).

Gracias chicos.

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
¿Fue útil?

Solución

Bueno, en SQL Server 2008, hay un nuevo tipo de datos llamado " DATE " - puedes usar esa columna y crear un índice en eso.

Por supuesto, también podría agregar una columna calculada de tipo " DATE " a su tabla y simplemente complete la parte de la fecha de la columna DATETIME en esa columna calculada, hágala PERSISTADA e indícela. ¡Debería funcionar bien!

Algo así:

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

CREATE UNIQUE INDEX UX_Entries ON Entries(DateOnly, Slug)

Marc

Otros consejos

Ya que estás en 2008, usa el tipo de datos Fecha como lo sugiere Marc. De lo contrario, una solución más fácil es tener una columna no calculada (lo que significa que tendrá que completarla en un INSERT) que usa la fecha en el formato AAAAMMDD. Es un tipo de datos enteros y es pequeño y fácil de usar.

Para SQL 2005, podría hacer básicamente lo mismo que marc_s recomienda, solo use un DateTime estándar. Se vería algo como esto (código no probado aquí):

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

Luego cree su índice en (JustTheDate, Slug)

Nota: la declaración DATEADD / DATEDIFF allí calcula solo la fecha de CompositionDate.

A lo largo de los años, hemos tenido una variedad de problemas con las columnas calculadas en SQL Server, por lo que hemos dejado de usarlas.

Podrías usar una VISTA con una columna solo para la fecha, y poner un índice único en la columna de esa VISTA.

(Un efecto colateral posiblemente útil es que puede hacer que la VISTA excluya algunas filas, por lo que podría implementar cosas como " DateColumn debe ser único, pero excluir DONDE DateColumn es nulo)

La columna CompositionDate existente se puede dividir en dos campos, CompositionDate y CompositionTime, y una Vista de recuperación que los une de nuevo si los necesita, lo que permitiría un índice nativo en la columna de solo fecha

(Esto puede implementarse en SQL 2005 y versiones anteriores usando DateTime, aunque es un poco extravagante solo por la fecha o la hora, y no por ambas)

Y, por último, podría tener un desencadenador INSERT / UPDATE que imponga que no existía ningún otro registro con un CompositionDate duplicado (solo parte de fecha)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top