Имя: Пароль:
1C
1С v8
Запись во внешние источники данных MySQL
,
0 Impuls20_03
 
12.10.20
14:56
Есть база на MySQL подключаю ее как внешний источник данных, импортирую таблицы. В таблице первичный ключ это varchar(100), автоинкремента нету. Проблема возникает когда я пытаюсь создать запись. Появляется ошибка: Описание: [MySQL][ODBC 8.0(w) Driver][mysqld-8.0.21]Truncated incorrect INTEGER value: '0000AD530FA3'
Где 0000AD530FA3 - это то, что я хочу записать в ключевое поле.

Если указать во внешнем источнике другое поле в качестве ключевого, но которое можно преобразовать в Integer - то запись проходит нормально. Нашел на мисте такую же проблему, но решения там так и не нашел: Внешние источники данных запись через 1с

Возможно есть какие-нибудь мысли по этому поводу?
1 МихаилМ
 
12.10.20
15:10
для записи ВИД не все драйвера MySQL подходят.
INTEGER - это 2 байта. в вашей ерунде (0000AD530FA3) точно больше.
как MySQL догадается, что  '0000AD530FA3'?
2 МихаилМ
 
12.10.20
15:11
что  '0000AD530FA3' - число ?
3 Impuls20_03
 
12.10.20
15:22
(1) На MySQL ключевое поле - это строка 100 символов. Я вместо 0000AD530FA3 - могу написать: HelloWorld123
К тому же я через тот же драйвер, только через ADODB.Command. Пишу SQL запрос Inser Into, где пишу все тоже самое. И этот запрос прекрасно отрабатывает и добавляет запись в таблицу.
4 arsik
 
гуру
12.10.20
15:29
(3) А если это поле совсем не указывать при инсерте?
5 Impuls20_03
 
12.10.20
15:34
(4) Первую запись запишет, вместо этого поля запишется 0, вторая запись не пройдет - будет ругаться на дублирующую запись. Если вместо текстового ключа писать числа - все будет записываться корректно.
6 arsik
 
гуру
12.10.20
15:41
(5) может все таки это поле не символьное?
7 Impuls20_03
 
12.10.20
15:47
(6) Хорошая попытка, но нет ))
https://ibb.co/kxtCwky
https://ibb.co/rsLFNtj
8 Impuls20_03
 
13.10.20
08:52
В общем включил логирование запросов на MySQL. Вот запрос, прилетающий от 1с.
INSERT INTO cardTemp  (idcard,
                        idcardgroup,
                        idclient,
                        number,
                        validitydatebeg,
                        validitydateend,
                        cardSum,
                        crc,
                        blocked,
                        ownerStoreId,
                        multiplicator,
                        multiplicatorbeg,
                        multiplicatorend,
                        multiplicatorcurrent,
                        lastKnownBonusBalance,
                        lastKnownBonusBalanceDate,
                        pincode,
                        cardstatus,
                        discountpercent,
                        purchases,
                        `update_time`,
                        status,
                        accountNumber)
VALUES(LAST_INSERT_ID('0000AD52FFA3'),
        '1',
        '1958',
        'B10000AD52FFA301',
        NULL,
        NULL,
        '0',
        NULL,
        NULL,
        NULL,
        '0',
        NULL,
        NULL,
        '0',
        NULL,
        '0001-01-01 00:00:00',
        '',
        '1',
        '0',
        '0',
        '2020-10-13 08:35:35',
        NULL,
        NULL)
9 Impuls20_03
 
13.10.20
08:58
В общем теперь вопрос. Можно ли 1с заставить не вставлять LAST_INSERT_ID в запрос?
10 VladZ
 
13.10.20
09:25
Сделай поле с первичным ключом числовым.
11 Impuls20_03
 
13.10.20
09:34
(10) Если бы я мог. Мне разработчики этой базы голову открутят, если я начну в ней что-то менять. К сожалению мне надо именно строку туда записывать.
12 arsik
 
гуру
13.10.20
09:37
(11) У тебя во внешнем источнике данных случаем функции не появились?
13 Impuls20_03
 
13.10.20
09:40
(12) Нет. Все таблицы. Функций нету.
14 Василий Алибабаевич
 
13.10.20
09:41
(12) Вообще то LAST_INSERT_ID() это встроенная функция mysql.
15 Impuls20_03
 
13.10.20
09:45
(14) Да я в курсе. Ее включает 1с-ка для всех ключевых полей, независимо от их типа. Вообще очень похоже на баг.
16 Василий Алибабаевич
 
13.10.20
09:46
+ (14) И не нужно хотеть в idcard что-то записать. Оно само. Это поле нужно пропустить и в запрос не передавать. И буитваммногасчастия
17 Impuls20_03
 
13.10.20
09:54
(16) Идея класс, но мне как раз таки туда нужно записать. Если бы мне оно не надо было, я бы, естественно, так и сделал.
18 novichok79
 
13.10.20
10:07
первое, что приходит на ум:
1. городить хранимую процедурку на стороне mysql и дергать ее из 1С.
2. исключить id из первичных ключей в свойствах таблиц внешнего источника данных в 1С.
19 Impuls20_03
 
13.10.20
10:20
(18) По поводу 1. Тут однозначно нет. Лезть в структуру БД мне никто не даст.
По поводу 2 сейчас копаю в данном направлении. Правда если я убираю все ключи - Таблица становится необъектной. И теперь я не могу вызвать метод СоздатьОбъект(). Наверное можно создавать набор записей. Но записей много и они каждый раз будут перезаписываться. Это резко будет нагружать сервере MySQL.
20 experimentator76
 
13.10.20
10:22
(19) ADO
21 Impuls20_03
 
13.10.20
10:28
(20) Если не найдется решения - видимо придется через ADO.
22 arsik
 
гуру
13.10.20
10:57
(21) Может тебе нужно перед записью УстановитьСсылкуНового для объекта сделать?
23 Impuls20_03
 
13.10.20
11:02
(22) Увы.((
24 arsik
 
гуру
13.10.20
11:04
(23) Это что значит?
25 Impuls20_03
 
13.10.20
11:15
(24) Это значит не прокатило. Он просто устанавливает ссылку на еще не записанный объект. И потом ее можно присвоить какому-нибудь реквизиту на форме.
26 Impuls20_03
 
13.10.20
11:19
Окей. Давайте переформулируем.
Я создаю менеджер записи. Все пишется как надо, но, почему-то вся таблица очищается и остается только последний записанный элемент. Очевидно что я где-то косячу, но не могу понять где

Для каждого карта из СписокОтсутствующихКарт Цикл
    новаяКарта                                 = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьМенеджерЗаписи();
    новаяКарта.idcard                        = карта.ИД;
    новаяКарта.idcardgroup                    = 1;               //Жестко определено - карты сотрудников
    новаяКарта.idclient                        = Формат(карта.БонуснаяКартаКод, "ЧН=0; ЧГ=");
    новаяКарта.number                        = "B1"+карта.ИД+"01";
    новаяКарта.blocked                        = Null;
    новаяКарта.cardstatus                    = 1;    //0 - начисление; 1 - начисление и оплата; 2 - заблокирована; 3 - только оплата
    новаяКарта.Записать(Истина);
КонецЦикла;
27 arsik
 
гуру
13.10.20
11:43
(26) Попробуй СоздатьКлючЗаписи
28 Impuls20_03
 
13.10.20
11:50
(27) Пробовал. Не работает это. Точнее ключ то он создает, а что с ним дальше делать непонятно. У менеджера записи есть метод Прочитать(), который, по идее, должен читать согласно установленного ранее ключа. Но опять таки он не принимает никаких параметров
29 arsik
 
гуру
13.10.20
11:56
(28) Мне кажется нужно
СоздатьКлючЗаписи()
прочитать()
ЗаполнитьОстальные поля
Записать()
30 Impuls20_03
 
13.10.20
12:05
(29) Не работает. То что СоздатьКлючЗаписи() ни на что не влияет это раз. Во вторых. Если в Таблице только одна запись - то прочитать() - возвращает ее, если в таблице 2 и более записи то появляется ошибка.  Запись не верна! Набор записей, принадлежащий менеджеру записи должен содержать ровно 1 запись. Ну т.е. что-то явно делается не так.
31 arsik
 
гуру
13.10.20
12:07
(30) Код приведи
32 arsik
 
гуру
13.10.20
12:08
+(31) Потому что ключ записи не указан.
33 experimentator76
 
13.10.20
12:12
(26) набор записей создай и наложи отбор
34 Impuls20_03
 
13.10.20
12:30
(31)
стр = новый Структура("idcard", карта.ИД);
ключЗаписи = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьКлючЗаписи(стр);
новаяКарта                         = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьМенеджерЗаписи();
новаяКарта.idcard                    = карта.ИД;
новаяКарта.Прочитать();
        
новаяКарта.idcard                    = карта.ИД;
новаяКарта.idcardgroup                    = 1;               //Жестко определено - карты сотрудников
новаяКарта.idclient                    = Формат(карта.БонуснаяКартаКод, "ЧН=0; ЧГ=");
новаяКарта.number                    = "B1"+карта.ИД+"01";
новаяКарта.blocked                    = Null;
новаяКарта.cardstatus                    = 1;    //0 - начисление; 1 - начисление и оплата; 2 - заблокирована; 3 - только оплата
новаяКарта.Записать(Ложь);

новаяКарта.idcard = карта.ИД; - без этого тоже не работает
35 Impuls20_03
 
13.10.20
12:33
(33) Да пробовал я набор создавать. Отбор не накладывается.
Набор = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьНаборЗаписей();
Набор.Отбор.idcard.Установить(карта.ИД);        // Не работает не видит поля idcard
Набор.Отбор.Добавить("idcard");                // 1C сообщает: Метод не доступен для данного объекта
36 novichok79
 
13.10.20
12:55
(35) отбор не накладывается, потому как во внешних источниках если таблица необъектная, у нее должны быть измерения.
а их у тебя нету. значит когда идет запись, оно сначала делает delete where измерение1 = значениеизмерения1
а потом insert. так как измерений нет, то просто делается delete from твоятаблица, делай через ADO, раз даже хранимку нельзя.
37 Impuls20_03
 
13.10.20
12:58
(36) Да я уже понял что глухо. Уже засел за ADO
38 arsik
 
гуру
13.10.20
13:00
(36) Так у него же есть измерение - idcard, уникальное. Возможно при подключении внешнего источника что то неправильно указал?
поле ключа то указано?
https://i.imgur.com/VpMOYH6.png
39 novichok79
 
13.10.20
13:01
(38) возможно 1С хреново с MySQL работает. я пробовал подрубиться к базе на MySQL и сделать запрос в конструкторе запросов 1С - там тупо удобнее и 1Сина валилась с непонятной ошибкой. я забил разбираться.
40 novichok79
 
13.10.20
13:02
(38) надо трейсить запросы которые шлет 1Сина в MySQL, без них сложно что-то сказать.
41 Impuls20_03
 
13.10.20
13:42
(40) Я же выкладывал запрос который 1с отправляет. Она в ключевое поле вставляет LAST_INSERT_ID('Текст ключа'). И MySQL на этом моменте сваливается. А если в свойствах таблицы 1с убрать все ключи, то таблица становится необъектной и получается то, что Вы и описали: 1с Шлет delete from cardTemp. Что собственно говоря и очищает всю таблицу. Остается единственный вариант - это создавать НаборЗаписей. Но его я использовать не хочу, потому как он сперва выгружает все записи из таблицы, а после того как его записать он снова их вгружает в СУБД. А это нагрузка и вообще ай яй яй так делать без отбора. А отбор сделать не получается потому что нет измерений)). Замкнутый круг

INSERT INTO cardTemp  (idcard,
                        idcardgroup,
                        idclient,
                        number,
                        validitydatebeg,
                        validitydateend,
                        cardSum,
                        crc,
                        blocked,
                        ownerStoreId,
                        multiplicator,
                        multiplicatorbeg,
                        multiplicatorend,
                        multiplicatorcurrent,
                        lastKnownBonusBalance,
                        lastKnownBonusBalanceDate,
                        pincode,
                        cardstatus,
                        discountpercent,
                        purchases,
                        `update_time`,
                        status,
                        accountNumber)
VALUES(LAST_INSERT_ID('0000AD52FFA3'),
        '1',
        '1958',
        'B10000AD52FFA301',
        NULL,
        NULL,
        '0',
        NULL,
        NULL,
        NULL,
        '0',
        NULL,
        NULL,
        '0',
        NULL,
        '0001-01-01 00:00:00',
        '',
        '1',
        '0',
        '0',
        '2020-10-13 08:35:35',
        NULL,
        NULL)
42 arsik
 
гуру
13.10.20
13:55
(41) Так надо подцепить, в источники, таблицу как необъектную, но с ключем.
43 Impuls20_03
 
13.10.20
15:05
(42) Вот я лопух. Точно. Такой вариант заработал как надо. Причем как с набором записей, так и с менеджером записи. Как говорится век живи, век учись.


набор = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьНаборЗаписей();
набор.Отбор.idcard.Установить(карта.ИД);
набор.Прочитать();
новаяКарта = набор.Добавить();
....
набор.Записать(Истина);



новаяКарта = ВнешниеИсточникиДанных.Artix.Таблицы.cardTemp.СоздатьМенеджерЗаписи();
новаяКарта.idcard = карта.ИД;
новаяКарта.Прочитать();
....
новаяКарта.Записать(Истина);
44 experimentator76
 
13.10.20
18:01
(43) Семен-семеныч! Это как бы подразумевалось, что ты не будешь мешать программе работать.
при добавлении таблицы 1С сама по большей части все делает что нужно...