SQL Server: установите дату на SQL-сервере, но оставайтесь детерминированными

(Это связано с Напишите дату на SQL сервере.)

Существует ли детерминированное выражение для определения DATETIME? Когда я использую это как формулу вычисляемого столбца:

DATEADD(dd, DATEDIFF(dd, 0, [datetime_column]), 0)

когда я помещаю индекс в этот столбец, я получаю сообщение об ошибке:

Cannot create index because the key column 'EffectiveDate' is non-deterministic or imprecise.

Но и DATEDIFF, и DATEADD по определению являются детерминированными функциями. Где подвох? Является ли это возможным?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
6
0
2 949
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ваш столбец [datetime_column] имеет значение по умолчанию, установленное на "getDate ()" ??

Если это так, поскольку функция getdate () не является детерминированной, это вызовет эту ошибку ...

Детерминированная или недетерминированная функция, определяемая пользователем, зависит от того, как функция кодируется. Пользовательские функции являются детерминированными, если:

  1. Функция привязана к схеме.
  2. Все встроенные или определяемые пользователем функции, вызываемые определяемыми пользователем функции детерминированы.
  3. Тело ссылки на функцию нет объектов базы данных за пределами объем функции. Например, детерминированная функция не может справочные таблицы кроме таблицы переменные, которые являются локальными для функция.
  4. Функция не вызывает никаких расширенные хранимые процедуры.

Пользовательские функции, не соответствующие этим критериям, помечаются как недетерминированные. Встроенные недетерминированные функции не допускаются в теле пользовательских функций.

getDate недетерминирован, я считаю, что это может быть причиной

kristof 21.11.2008 20:32

Но это просто значение по умолчанию. Это не часть формулы. Кстати, я получаю ту же ошибку для столбца NULL по умолчанию.

Tomalak 21.11.2008 20:42

Я предполагаю, что подпрограмма, которая делает это, не различает ту часть определения столбца, которая представляет формулу, и часть, которая представляет значение по умолчанию ...

Charles Bretana 21.11.2008 20:58

Да, это так. Я пробовал предложение Кристофа.

Tomalak 21.11.2008 22:42

Попробуй это:

CAST(FLOOR(CAST([datetime_column] as FLOAT)) AS DateTime)

Это должно происходить намного быстрее, чем опция ПРЕОБРАЗОВАТЬ.

CAST не является детерминированным для значений даты и времени.

Tomalak 21.11.2008 20:31

Посмотрите на на этот вопрос задал и ответил Кейд Ру. Возможно, решением было бы создать функцию с использованием WITH SCHEMABINDING, а затем использовать ее в вычисляемом столбце

РЕДАКТИРОВАТЬ

Я понимаю, что ваша цель - иметь индекс для этого столбца.

Если это невозможно сделать с вычисляемым столбцом, то, возможно, единственным вариантом будет создание обычного столбца и изменение данных в этом столбце каждый раз, когда вы обновляете столбец, на котором он основан. (сказать в триггере)

Я бы предложил несколько попроще:

 cast(cast([datetime_column] as int) as datetime)

но я подозреваю, что вы столкнетесь с той же проблемой.

Теперь, если проблема заключается в возврате к дате и времени, вы можете рассмотреть возможность использования только cast([datetime_column] as int) в качестве отдельного поля, только для индекса.

Проблема также связана с приведением из datetime (или convert () ing, если на то пошло).

Tomalak 21.11.2008 21:26
Ответ принят как подходящий

Я предполагаю, что это своего рода ошибка. В SQL 2005 мне удалось без проблем создать такое индексированное представление (код ниже). Когда я попытался запустить его на SQL 2000, я получил ту же ошибку, что и вы.

Следующее, похоже, работает с SQL 2000, но я получаю предупреждение о том, что индекс будет проигнорирован, и вам придется преобразовывать каждый раз, когда вы выбираете из представления.

CONVERT(CHAR(8), datetime_column, 112)

Работает в SQL 2005:

CREATE TABLE dbo.Test_Determinism (
    datetime_column DATETIME    NOT NULL    DEFAULT GETDATE())
GO

CREATE VIEW dbo.Test_Determinism_View
WITH SCHEMABINDING
AS
    SELECT
        DATEADD(dd, DATEDIFF(dd, 0, [datetime_column]), 0) AS EffectiveDate
    FROM
        dbo.Test_Determinism
GO

CREATE UNIQUE CLUSTERED INDEX IDX_Test_Determinism_View ON dbo.Test_Determinism_View (EffectiveDate)
GO

Вот мой лучший ответ на исходный вопрос:

Попробуй это:

/* create a deterministic schema bound function */
CREATE FUNCTION FloorDate(@dt datetime)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN 
    RETURN CONVERT(datetime,  FLOOR(CONVERT(float, @dt)))
END
GO

Для проверки попробуйте следующее. Обратите внимание на использование «PERSISTED» для вычисляемого столбца и использование [dbo.] При обращении к функции

/*create a test table */
CREATE TABLE [dbo].[TableTestFloorDate](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [TestDate] [datetime] NOT NULL,
    [TestFloorDate]  AS ([dbo].[FloorDate]([TestDate])) PERSISTED,
 CONSTRAINT [PK_TableTestFloorDate] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
) 

Теперь у вас должна быть возможность добавить индекс в вычисляемый столбец (но см. Попытки позже)

CREATE INDEX IX_TestFloorDate ON  [dbo].[TableTestFloorDate](TestFloorDate)

Вставляйте случайные данные столько раз, сколько хотите, но больше (1000+) лучше, если вы хотите протестировать планы использования / выполнения индекса.

INSERT INTO TableTestFloorDate (TestDate) VALUES( convert(datetime, RAND()*50000))

Получите результат

SELECT * FROM TableTestFloorDate WHERE TestFloorDate='2013-2-2'

А вот и GOTCHA ... Индекс, созданный для вычисляемого столбца, не используется! Вместо этого, даже при выборе данных в постоянном поле TestFloorDate, SQLServer (или, по крайней мере, моя версия) предпочитает индекс на TestDate.

CREATE INDEX IX_TestFloorDate ON  [dbo].[TableTestFloorDate](TestDate)

Я почти уверен (по памяти), что индексы для вычисляемых постоянных столбцов имеют преимущество с точки зрения производительности - я думаю, вам просто нужно попробовать / протестировать для ваших собственных конкретных применений

(Надеюсь, я помог!)

У меня нет возможности проверить это прямо сейчас. Совместим ли этот SQL Server 2000 (я знаю, что он старый, но теги в вопросе указывали на эту версию)?

Tomalak 24.07.2013 15:05

Вышеупомянутое было протестировано в Sql2012, но по памяти я не понимаю, почему это не работает на Sql2k точно так, как описано выше.

dunxz 25.07.2013 18:23

Другие вопросы по теме