Я что-то не так делаю?
Почему он использует свое (неправильное) индексное имя вместо имени, которое я ему дал?
Кажется, вы все делаетев самый раз.Проблема заключается в сгенерированной команде SQL, которую вы отследили.SQL Server не допускает имя схемы в имени ограничения при добавлении ограничения с использованием ALTER TABLE
.Ограничения, созданные таким образом, автоматически становятся частью схемы связанной таблицы, однако вам следует позже использовать имя схемы при ссылке на ограничение:
SELECT OBJECT_ID('cnf.PK_XYZ')
Теперь, где все идет не так?FireDAC использует TFDPhysCommandGenerator
и его предков для генерации команд SQL для конкретной СУБД.Ваш вызов метода CreateTable
приводит к вызову TFDPhysCommandGenerator.GetCreatePrimaryKey
, который отвечает за генерацию SQL для первичного ключа.Он также содержит этот код:
sTab := GetFrom;
FConnMeta.DecodeObjName(sTab, rName, nil, [doUnquote]);
rName.FObject := 'PK_' + rName.FObject;
Result := 'ALTER TABLE ' + sTab + ' ADD CONSTRAINT ' +
FConnMeta.EncodeObjName(rName, nil, [eoQuote, eoNormalize]) + ' PRIMARY KEY (';
Этот код делает то, что он принимает ваше полное имя таблицы (sTab
), разбивает его (DecodeObjName
) на части (rName
) и добавляет 'PK_'
к имени таблицы и присоединяет детали (EncodeObjName
) к полному имени, которое затем используется в качестве имени ограничения для вашего первичного ключа.Теперь мы можем ясно видеть, что генератор команд игнорирует имя вашего индекса и генерирует ошибочный T-SQL.Это может быть ошибка или просто не поддерживаемая функция.EMBT должен принять решение по этому вопросу.Я бы рекомендовал сообщить об этом как об ошибке.
Есть ли обходной путь?
Да, вы можете перехватить проблемный метод или переопределить его в своемсобственный производный класс.Реализация ничего из этого не является тривиальной, и из-за юридических проблем я не собираюсь расширять ее здесь, потому что мне пришлось бы дублировать исходный код FireDAC.
Что касается синтаксической ошибки, добавив эти строки в 'TFDPhysCommandGenerator.Реализация GetCreatePrimaryKey после DecodeObjName
решит проблему:
rName.FCatalog := '';
rName.FSchema := '';
rName.FBaseObject := '';
rName.FLink := '';
Исправление имени ограничения будет более громоздким, чем то, потому что метод получает только имена столбцов индекса в качестве аргумента и не имеет очевидного доступа к оригиналуIndexDefs
, где вы можете просто использовать имя индекса в качестве имени ограничения первичного ключа.Получение доступа к имени индекса оттуда также позволит вам избавиться от имени таблицы декодирования / кодирования в имени индекса.Однако этот процесс может быть важен для других DMBS, отличных от SQL Server.
PS: Если бы только половина всех вопросов была написана таким образом ... Спасибо за этот замечательный вопрос.