Невозможно сделать вычисляемый столбец индексируемым - PullRequest
0 голосов
/ 04 октября 2018
CREATE FUNCTION dbo.FN_GET_YEAR(@ID int) RETURNS int WITH SCHEMABINDING AS
BEGIN
    RETURN (SELECT YEAR(begin_date) FROM dbo.tableName WHERE id = @ID);
END

GO

CREATE TABLE test_table (
    id int,
    fk_id int,
    test AS dbo.FN_GET_YEAR(id)
);

SELECT COLUMNPROPERTY(OBJECT_ID('test_table'), 'test', 'IsIndexable') AS IsIndexableColumn;

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

Однако, несмотря на то, что я попробовал все предложения онлайн, я не уверен, что мне не хватает.Я использовал ключевое слово «С SCHEMABINDING», а также пробовал с и без CONVERT / CAST.Проблема в том, что столбец не является детерминированным, но в документации также говорится, что YEAR () является детерминированным.

Если я просто верну объявленное статическое значение в функции, тогда столбец станет индексируемым.ГОД (), кажется, сломал это.

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

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

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

"Мне нужно ограничить использование внешнего ключа и годовой комбинации одним разом в год. Так что это будет УНИКАЛЬНЫЙ индекс."

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

Вы можете сделать этот видвещь с индексированным представлением.EG:

drop view if exists v_test_table_year
drop table if exists test_table
drop table if exists tablename
go
create table tableName(id int, begin_date datetime)

go

CREATE TABLE test_table (
    id int,
    fk_id int--,
   -- test AS dbo.FN_GET_YEAR(id)
);

go
create or alter view v_test_table_year
with schemabinding
as
select year(tn.begin_date) year
from dbo.test_table t
join dbo.tableName tn
  on t.fk_id = tn.id

 go
 create unique clustered index ci_v_test_table_year
 on v_test_table_year(year)

 go

 insert into tableName(id,begin_date) values (1,'2017-01-01')
 insert into tableName(id,begin_date) values (2,'2017-02-01')

 insert into test_table(id,fk_id) values (1,1) --ok
 insert into test_table(id,fk_id) values (2,2) --fails
0 голосов
/ 04 октября 2018

У меня есть функция, которая возвращает год заданной даты, а затем эта функция используется в качестве вычисляемого столбца

Это не то, что вы опубликовали.Вы опубликовали функцию, которая возвращает текущий год, который явно не является детерминированным.

Вы можете написать функцию, которая возвращает год указанной даты и использовать ее в индексированном вычисляемом столбце:

CREATE FUNCTION dbo.FN_GET_YEAR(@d datetime) RETURNS int WITH SCHEMABINDING AS
BEGIN
    RETURN YEAR(@d);
END

GO

CREATE TABLE test_table (
    id int,
    dateCol datetime,
    test AS dbo.FN_GET_YEAR(dateCol)
);

SELECT COLUMNPROPERTY(OBJECT_ID('test_table'), 'test', 'IsIndexable') AS IsIndexableColumn;

create index ix_test_table_test on test_table(test)
...