Имя: Пароль:
IT
 
Проблема связки Delphi: TFireDAC+MSSQL+TVP+datetime2(0)
0 H A D G E H O G s
 
06.03.23
22:04
День добрый.
Понадобился мне вот механизм вставки в MS SQL сервер достаточно больших таблиц данных. 2-ым этим парнем на деревне после BULK INSERT был признан механизм вставки через TVP (табличные параметры процедур). Смысл его в том, что на сервере MS SQL создается табличный тип с колонками, идентичными таблице, куда следует поместить данные, к этому типу – хранимая процедура, которая выполняет помещение через Insert, примерно так:
CREATE PROCEDURE [dbo].[Create_ MyTable _TVP] (
   @ImportTable dbo.Create_ MyTable _TVPStructure READONLY
)
AS
SET NOCOUNT ON;
SET DATEFORMAT dmy;
INSERT INTO dbo.MyTable
    SELECT  *
    FROM    @ImportTable;

И все идет отлично, скорость офигенная, но до тех пор, пока я не стал передавать тип DateTime2. Firedac стал выкидывать ошибку назависимо от типа драйвера:
[FireDAC][Phys][ODBC][Microsoft][SQL Server Native Client 11.0]Переполнение поля Datetime. Точность в долях секунды превышает масштаб, указанный в привязке параметра.
[FireDAC][Phys][ODBC][Microsoft][ODBC Driver 17 for SQL Server]Переполнение поля Datetime. Точность в долях секунды превышает масштаб, указанный в привязке параметра.
С типом datetime – ситуация – аналогичная. Я перепробовал уже все мыслимое и немыслимое, все настройки Firedac излазил, ничего не помогает.
Проблема в том, что Firedac – крайне трудная в отладке ioba, я уже спустился на уровень SQL Binding, но пока не могу найти причину, или даже настройку округления или точности Firedac.
Параметр хранимой процедуры я устанавливаю просто как TDataSet, это не скалярный параметр, и никаких настроек для него я задать не могу:
FDStoredProc1.ParamByName('@ImportTable').SetDataSet(FDMemTable1, false);
Пока, из ситуации, я вышел, передавая строковые представления дат, а в хранимой процедуре делаю обратную конвертацию через Convert(), но это неправильно. Нужна помощь.
Тестовый проект на Delphi 11 выложен тут (просто исходники, никаких dcu, dll, exe):

https://github.com/Hadgehogs/DemoTFireDacFail

Для работы, необходима Delphi 11 (но, скорее всего, пойдет и более ранняя версия), MS SQL 2019 (но возможно подойдет и более ранняя версия)
1 Garykom
 
гуру
06.03.23
22:15
1. C# вместо Delphi
https://khalidabuhakmeh.com/passing-table-valued-parameters-from-dotnet-to-sql-server
2. Передавай строку и конверти в хранимке
2 H A D G E H O G s
 
06.03.23
22:19
(1) Ты невнимательно читал. Давай я повторю:
"Пока, из ситуации, я вышел, передавая строковые представления дат, а в хранимой процедуре делаю обратную конвертацию через Convert(), но это неправильно."
3 Garykom
 
гуру
06.03.23
22:20
(2) Ну и забей на этом
Потому что разбираться в древних и уже хреново поддерживаемых технологиях такое себе
4 Garykom
 
гуру
06.03.23
22:22
затести еще CAST вместо CONVERT
там формат строки под DataTime2 надо подогнать но возможно будет шустрей
5 Garykom
 
гуру
06.03.23
22:32
на C# вроде как пашет, если порядок колонок не нарушать
https://stackoverflow.com/questions/8335994/ado-net-table-valued-parameter-tvp-operand-type-clash-datetime2-is-incompati
6 Кирпич
 
07.03.23
08:30
Вроде написано, что масштаб не тот. какой масштаб у DateTime2 в Delphi и SQLServer?
Тут вабще пишут, что ODBC не понимает DateTime2
https://docwiki.embarcadero.com/RADStudio/Sydney/en/MS_SQL_Server_Questions_(FireDAC)
7 Кирпич
 
07.03.23
08:34
8 NorthWind
 
07.03.23
08:46
а DBGo (ADO) умерло в свежих версиях дельфи?
9 H A D G E H O G s
 
07.03.23
12:05
(6) (7) Когда datetime2(0) меняешь на datetime - точно такая же ошибка.
10 H A D G E H O G s
 
07.03.23
12:05
(8) Нет.
11 Кирпич
 
07.03.23
12:13
(9) А поменять на datetime2(7) ?
12 H A D G E H O G s
 
07.03.23
12:13
(11) Точно также
13 NorthWind
 
07.03.23
12:14
(10) так может, есть попробовать в этом направлении?
Все ж посовременнее чем ODBC
14 NorthWind
 
07.03.23
12:15
* есть смысл
15 H A D G E H O G s
 
07.03.23
12:21
(13) dbGo (AdoStoredProc) не умеет работать с параметрами - табличными частями
16 Кирпич
 
07.03.23
13:06
поставь полю тип ftTimeStamp
17 H A D G E H O G s
 
07.03.23
13:50
(16) Сработало!
18 H A D G E H O G s
 
07.03.23
13:50
(16) Это просто попадание наугад или есть инфа или опыт?
19 Кирпич
 
07.03.23
13:51
Это гугл
20 H A D G E H O G s
 
07.03.23
13:51
(19) Кинь ссылку
21 XLife
 
07.03.23
14:20
22 Кирпич
 
07.03.23
15:20
23 Кирпич
 
07.03.23
15:21
Datetime2    
SQL_TYPE_TIMESTAMP
SQL_TIMESTAMP
24 H A D G E H O G s
 
07.03.23
16:00
(22) (23) Спасибо!
25 Garykom
 
гуру
07.03.23
16:01
Потом потребуется передача бинарных данных (например картинки в базе) и тоже упс
26 H A D G E H O G s
 
07.03.23
16:11
(25) Не потребуется. Это парсинг Техжурнала.
Независимо от того, куда вы едете — это в гору и против ветра!