Версия для печати темы (https://pro1c.org.ua/index.php?showtopic=17801)

Нажмите сюда для просмотра этой темы в обычном формате

Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 _ Программирование в 1С Предприятие 7.7 _ Прямая запись данных в SQL-таблицы: УИД 1С в uniqueidentifier SQL

Автор: Vava 05.05.14, 21:46

Необходимо записывать данные во внешние таблицы MS SQL 2005. В таблице тип данных поля, в которое необходимо записывать данные - уникальный идентификатор. В 7-ке я формирую идентификатор функцией ПолучимГУИДSQL(), в результате работы которой получаю строковое значение вида: "16700000-0001-0000-0000-000000000000"


    cmd=СоздатьОбъект("ADODB.Command");
    cmd.ActiveConnection=Соединение;
    cmd.CommandTimeOut=600;
    cmd.CommandType=1;
    cmd.Prepared = "True";
    cmd.NamedParameters = "True";
    cmd.Commandtext ="INSERT INTO tbl_Account (Account1CID)     VALUES (Convert(uniqueidentifier, ?))";
    
    cmd.Parameters.Append(cmd.CreateParameter("@Account1CID"    , 202,1,36));

    ТЗКонтрагенты.ВыбратьСтроки();

    Соединение.BeginTrans();
    пСтрока = ПолучимГУИДSQL(ТЗКонтрагенты.Account1CID);
    Пока ТЗКонтрагенты.ПолучитьСтроку() = 1 Цикл
        cmd.Parameters("@Account1CID").Value     = ПолучимГУИДSQL(ТЗКонтрагенты.Account1CID);
        cmd.Execute();
    КонецЦикла;


При выполнении кода возникает ошибка:
cmd.Execute();
{D:\WORK\EXTFORMS\SQL.ERT(291)}: Microsoft OLE DB Provider for SQL Server: Conversion failed when converting from a character string to uniqueidentifier.


Такая же возникает при попытке присвоить в лоб:
cmd.Parameters("@Account1CID").Value     =  "16700000-0001-0000-0000-000000000000";


Каким образом правильно записывать значения подобного типа. Может кто сталкивался с подобными задачами?
Спасибо

Автор: sava1 06.05.14, 6:55

типа так
INSERT INTO MyUniqueTable VALUES (NEWID(), 'def')

Автор: Vofka 06.05.14, 8:01

cmd.Commandtext ="INSERT INTO tbl_Account (Account1CID) VALUES (CAST('"+СокрЛП(Гуид1С)+"' as UNIQUEIDENTIFIER))";

Автор: Vava 06.05.14, 8:38

sava1, как я понял таким образом будет создано и записано в таблицу новое уникальное значение. Используя свой уникальный код потом можно определить какому элементу принадлежит запись. Потом нужно будет по этому значению находить эту строку и вносить изменения в данные. Контрагент записан со всеми своими данными и при изменении их в 1с нужно вносить изменения и в БД.

Vofka, попробовал так:

ГУИДКонтрагента = ПолучимГУИДSQL(ТЗКонтрагенты.Account1CID);
cmd.Commandtext ="INSERT INTO tbl_Account (Account1CID)     VALUES (CAST('"+ГУИДКонтрагента+"' as UNIQUEIDENTIFIER))";


Получил:

cmd.Execute();
{D:\WORK\ИНТЕРСТАЛЬ\EXTFORMS\SQL.ERT(294)}: Microsoft OLE DB Provider for SQL Server: Произошли ошибки во время выполнения многошаговой операции OLE DB. По возможности, проверьте значения всех состояний OLE DB. Работа не выполнена.


Может есть мысли какие?

Автор: Vofka 06.05.14, 8:47

А что находится в переменной ГУИДКонтрагента ?

Цитата(Vofka @ 06.05.14, 9:01) *
...СокрЛП(Гуид1С)...

Автор: Vava 06.05.14, 8:51

Функция ПолучимГУИДSQL() возвращает строковое значение вида: "16700000-0001-0000-0000-000000000000"

Это строка. Пробелов там нет. Функция формирует из 12-ти значного числа УИДа элемента справочника

Автор: sava1 06.05.14, 8:58

может поможет ? http://pro1c.org.ua/redirect.php?http://www.1cpp.ru/forum/YaBB.pl?num=1192605250/0#0

Автор: Vava 06.05.14, 9:24

sava1, попробовал. Такая же ошибка

Автор: sava1 06.05.14, 10:10

А зачем в таблице ГУИД? Как получаете ГУИДКонтрагента?

Автор: Vava 06.05.14, 10:23

sava1, из этой таблицы БД другая программа забирает данные. УИД изначально получен с помощью функции:

Функция ПолучимГУИД77(Объект)
    Стр=ЗначениеВСтрокуВнутр(Объект);
    СЗ=СоздатьОбъект("СписокЗначений");
    СЗ.ИзСтрокиСРазделителями(Сред(Стр,2,СтрДлина(Стр)-2));  
    ГУИД=формат(СЗ.ПолучитьЗначение(4),"Ч(0)5")+Формат(сокрлп(СЗ.ПолучитьЗначение(СЗ.РазмерСписка())),"Ч(0)9");
    Возврат ГУИД;
КонецФункции    // ПолучимГУИД77


Полученное 12-тизначное число приводится к виду: "16700000-0001-0000-0000-000000000000". Первые 12 знаков значащие. Остальные забиваю нолями.

Автор: Vofka 06.05.14, 10:36

А непосредственно на SQL-е такой запрос выполняется:

SQL
INSERT INTO tbl_Account (Account1CID) VALUES (CAST('16700000-0001-0000-0000-000000000000' as UNIQUEIDENTIFIER))

?

И, собственно, учитывая это:
Цитата(Vava @ 06.05.14, 11:23) *
Полученное 12-тизначное число приводится к виду: "16700000-0001-0000-0000-000000000000". Первые 12 знаков значащие. Остальные забиваю нолями.

почему не использовать на SQL-е тип данных "число" или "строка"?

Автор: Vava 06.05.14, 10:46

Vofka, дело в том, что база уже есть и нужно писать в нее.
Попробую на SQL-е непосредственно. Пока нет возможности.

Автор: logist 06.05.14, 11:26

А зачем изобретать УИД? Ведь ссылка 1C содержит в себе УИД под которым она и хранится в своей базе.

Автор: Vava 06.05.14, 11:45

logist, а как извлекается такой УИД в 7-ке?

Автор: sava1 06.05.14, 12:55

Цитата(logist @ 06.05.14, 12:26) *
А зачем изобретать УИД?

Как я понял - таблица уже есть и она внешняя и на нее уже что-то завязано - и не ясно вообще-то где получится велосипед.
Склоняюсь к проблеме с драйвером Адо.
ТС - проверьте запрос из #11

Автор: Vava 06.05.14, 13:58

Удалось записать. Всю цепочку действий не восстановлю. Думаю, что ключевым моментом было то, что в таблице есть поле обязательное для заполнения -уникальный идентификатор строки таблицы. Без его заполнения строка не записывалась. Буду разбираться дальше. Спасибо всем за участие!

А как быть, если элемент, УИД которого надо писать, не выбран?

Автор: sava1 06.05.14, 14:07

Заполнить по дефолту, хотя ключевое поле не пропустит - если это ГУИД - прописать NewID()

Автор: Vava 06.05.14, 14:15

Наверное было бы правильно в таком случае писать Null, если это допускается.
Но как это предусмотреть в конструкции:

    cmd.Commandtext="INSERT INTO tbl_Account (ID, Account1CID, Owner1CID)     
    |VALUES (NEWID(),
    |CAST('"+ПолучимГУИДSQL(ТЗКонтрагенты.Account1CID)+"' as UNIQUEIDENTIFIER),
    |CAST('"+ПолучимГУИДSQL(ТЗКонтрагенты.Owner1CID)+"' as UNIQUEIDENTIFIER)
    |)";

если значение ТЗКонтрагенты.Owner1CID = 0?

Или не писать вообще ничего...

Автор: logist 06.05.14, 14:20

Цитата(Vava @ 06.05.14, 14:15) *
если значение ТЗКонтрагенты.Owner1CID = 0?

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

Автор: Vava 06.05.14, 14:24

Пока на ум пришло записывать в УИД "00000000-0000-0000-0000-000000000000", а потом , при необходимости обрабатывать такие значения.

logist, но тогда мы получим

SQL
CAST('Null' as UNIQUEIDENTIFIER)

И возникнет ошибка преобразования типа. Уже пробовал )

Автор: logist 06.05.14, 15:20

Цитата(Vava @ 06.05.14, 14:24) http://pro1c.org.ua/index.php?act=findpost&pid=86448
но тогда мы получим

А переписать так, что бы при Null не делать запись этого поля?

Автор: Vava 06.05.14, 16:36

logist, не записывать конечно правильно. Но как реализовать? Можно записывать обязательные поля, а потом по ним искать и дописывать остальные данные. Может есть способ оптимальней?

Автор: Vava 07.05.14, 12:31

Разобрался. Спасибо всем за помощь!

Автор: Vofka 07.05.14, 13:13

Vava, и?

Автор: Vava 07.05.14, 16:52

Vofka, как я и писал, строка не записывалась из-за того, что я не заносил значение в поле, обязательное для заполнения "ID".
Приведенный ниже код позволил записывать данные в таблицу БД, с учетом неполных данных. Если данные отсутствуют - запись в БД не происходит.

        Соединение.BeginTrans();
        
        Пока ТЗКонтрагенты.ПолучитьСтроку() = 1 Цикл
        
            Команда="INSERT INTO tbl_Account (ID, Account1CID, Owner1CID, Name, UNP, OKPO, InThePersonOf, FIO, Base, Status, CreatedOn)     
            |VALUES (NEWID(),
            |CAST('"+ПолучимГУИДSQL(ТЗКонтрагенты.Account1CID)    +"' as UNIQUEIDENTIFIER), ";
            
            Если ПустоеЗначение(ТЗКонтрагенты.Owner1CID)=0 Тогда
                Команда = Команда + "CAST('"+ПолучимГУИДSQL(ТЗКонтрагенты.Owner1CID)    +"' as UNIQUEIDENTIFIER), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;
            
            Если ПустоеЗначение(ТЗКонтрагенты.Name)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.Name +"' as CHAR(120)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;

            Если ПустоеЗначение(ТЗКонтрагенты.UNP)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.UNP +"' as CHAR(13)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;

            Если ПустоеЗначение(ТЗКонтрагенты.OKPO)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.OKPO +"' as CHAR(12)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;

            Если ПустоеЗначение(ТЗКонтрагенты.InThePersonOf)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.InThePersonOf +"' as CHAR(8)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;

            Если ПустоеЗначение(ТЗКонтрагенты.FIO)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.FIO +"' as CHAR(40)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;

            Если ПустоеЗначение(ТЗКонтрагенты.Base)=0 Тогда
                Команда = Команда + "CAST('"+ТЗКонтрагенты.Base +"' as CHAR(5)), ";
            Иначе                
                Команда = Команда + "Null, ";
            КонецЕсли;
            
            Команда = Команда + "CAST('"+ТЗКонтрагенты.Status +"' as SMALLINT), CAST('"+СокрЛП(РабочаяДата())+"' as DATETIME))";
            
            cmd.Commandtext = Команда;
            cmd.Execute();
        КонецЦикла;
        
        Соединение.CommitTrans();


Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7
https://pro1c.org.ua