Имя: Пароль:
1C
1С v8
Как передать в ADODB в запрос параметр типа массив?
0 DomovoiAtakue
 
24.04.19
12:15
Подключаюсь к базе ADODB  и запросом хочу вытащить данные. В запрос мне надо передать строковый массив.

Соединение1 = Новый COMОбъект("ADODB.Connection");
Соединение1.Open(СтрокаСоединения);
Cmd1 = Новый COMОбъект("ADODB.Command");
Cmd1.ActiveConnection = Соединение1;
Cmd1.CommandText = Запрос;

МТМЦ = Новый Массив;
//Заполняем массив строковыми значениями, длина 40 символов.

Парам  = Новый COMОбъект("ADODB.Parameter");
Парам.Name = "@TMC";
Парам.Type = "0x2000";
Парам.Size = МТМЦ.Количество();
Парам.Direction = 1;
Парам.Value = МТМЦ;

Cmd1.Parameters.Append(Парам);

Rs1 = Новый COMОбъект("ADODB.RecordSet");
Rs1 = Cmd1.Execute();


В строке <<Парам.Value = МТМЦ;>> уже ошибку дает. Как правильно передать параметр?
1 Rie
 
24.04.19
12:24
Возможно, поможет ComSafeArray.
2 DomovoiAtakue
 
24.04.19
12:35
(1)Помогло. Переписал на:

КомМассив = Новый COMSafeArray(МТМЦ, "VT_BSTR",МТМЦ.Количество());
            
Парам  = Новый COMОбъект("ADODB.Parameter");
Парам.Name = "@TMC";
Парам.Type = "0x2000";
Парам.Size = МТМЦ.Количество();
Парам.Direction = 1;            
Парам.Value = КомМассив;
            
Cmd1.Parameters.Append(Парам);

Теперь ошибка в <<Cmd1.Parameters.Append(Парам);>> Наверное неправильно задаю данные параметра. Что нужно исправить?
3 1Сергей
 
24.04.19
12:36
(2) прикольный текст ошибки
4 DomovoiAtakue
 
24.04.19
12:39
(3)Ошибка при вызове метода контекста (Append)
            Cmd1.Parameters.Append(Парам);
по причине:
Произошла исключительная ситуация (ADODB.Parameters): Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения.
5 arsik
 
гуру
24.04.19
12:40
Парам.Type = "0x2000"; - там точно строка должна быть?
6 DomovoiAtakue
 
24.04.19
12:43
(5)не знаю. А как это записать еще?
7 Кирпич
 
24.04.19
12:51
(6) попробуй вместо строки "0x2000" написать число 8192
8 Кирпич
 
24.04.19
12:53
а собаку в имени параметра обязательно писать?
9 DomovoiAtakue
 
24.04.19
12:53
(7)Нашел тему на форуме где предложили данный вариант, но он не прокатил ни там. ни у меня.

Ошибка при установке значения атрибута контекста (Type)
            Парам.Type = 8192;
по причине:
Произошла исключительная ситуация (ADODB.Parameter): Аргументы имеют неверный тип, выходят за пределы допустимого диапазона или вступают в конфликт друг с другом.
10 DomovoiAtakue
 
24.04.19
12:55
(8)Не знаю. В статьях в примерах так пишут и я так написал.
11 Кирпич
 
24.04.19
12:57
(9) А. Там наверное надо прибавить тип элементов массива
12 DomovoiAtakue
 
24.04.19
12:58
(11)Я не очень понимаю что это и как это? Что мне написать? :)
13 Кирпич
 
24.04.19
12:58
попробуй 8192+8
14 Кирпич
 
24.04.19
12:59
adBSTR     8     Указывает строку символов с завершающим нулем (Юникод) (DBTYPE_BSTR).

AdArray     0x2000     Значение флага всегда в сочетании с другой константой типа данных, который указывает массив другого типа данных. Не применяется к ADOX.
15 Кирпич
 
24.04.19
13:33
Так заработало или нет?
16 DomovoiAtakue
 
24.04.19
13:41
(15)На стадии передачи параметра заработало, но выдало ошибку при выполнении запроса. Вот пытаюсь понять то ли все-таки параметр не так передал то ли что еще?
17 Кирпич
 
24.04.19
13:58
ну покажи запрос тогда
18 SSSSS_AAAAA
 
24.04.19
14:01
(0) А в каких СУБД есть тип "массив"? СУБД, для которой пишется запрос, входит в этот список?
19 DomovoiAtakue
 
24.04.19
14:18
(17)Cmd1.CommandText = "SELECT p.group_id,  p.art
            |from ns.products p
            |where p.art in @TMC";

Без условия на параметр запрос работает.
А с параметром выдает ошибку на строке
"Rs1 = Cmd1.Execute();"

Rs1 = Cmd1.Execute();
по причине:
Произошла исключительная ситуация (Provider): Неизвестное имя типа.
20 DomovoiAtakue
 
24.04.19
14:20
(18)Не знаю.
21 NorthWind
 
24.04.19
14:29
(19) > where p.art in @TMC
Крутяк. А почему вы решили, что это вообще будет работать? Вы где-то находили рабочий пример для вашей БД, где содержимое IN (...) так передавалось?
22 fisher
 
24.04.19
14:31
Я когда-то решал эту задачу в MSSQL через XML. Там были встроенные функции, позволяющие одной командой распарсить XML и вернуть результат в виде таблицы. Ну и я в 1С пихал элементы массива в XML, на стороне сиквела конвертировал xml во временную таблицу, ну а дальше уже понятно.
23 NorthWind
 
24.04.19
14:35
(22) такой вариант не пробовал, хотя он вполне имеет право на существование.
Можно решить через временную таблицу - проинсертить в нее параметры, а потом сделать IN (select col from temp_tbl where id=:id)
Можно сформировать строку ('aaaa', 'bbb', ...) и потом сформировать с ней запрос, обойдясь без параметров. Но при этом надо помнить, что многие БД имеют ограничение на количество элементов в таком списке.
24 NorthWind
 
24.04.19
14:35
а вот если бы было возможно (19) - это была бы песня. Но чет мне кажется, что это фантастика.
25 DomovoiAtakue
 
24.04.19
14:36
(21)В данной базе нет примеров передачи параметра в запрос. Но если я напишу в запросе вместо параметра IN ('3453','245','64564'), то работает. Внутри скобок по сути массив, ну я и решил что можно передать туда массив и должно заработать.
26 NorthWind
 
24.04.19
14:38
(25) я не могу вам привести пруфов, как и вы мне. Но вероятность около 95%, что так сделать не получится. Во всяком случае мне еще не попадался SQL, который позволял бы передавать параметром множество в IN.
27 DomovoiAtakue
 
24.04.19
14:40
Понятно. Будем пробовать по-другому :)
28 NorthWind
 
24.04.19
14:41
я в такой ситуации либо собирал запрос ручками без параметра (если элементов заведомо не очень много, либо делал через временную таблицу. Вон, (22) еще через XML советует, тоже вариант.
29 fisher
 
24.04.19
14:52
Во, нашел. Лет 5 назад делал, может кому пригодится. Делал только для массива числовых айдишников под свои хранимки, принимающие массив в качестве параметра типа xml. Но, думаю, нетрудно адаптировать и под "голый" sql-скрипт без доп-функций и хранимок.
Функция ПолучитьМассивXML(МассивID) Экспорт
    
    МассивXML = "";
    
    Для Каждого ID Из МассивID Цикл
        МассивXML = МассивXML + "<a e="""+Формат(ID,"ЧГ=0")+"""></a>";
    КонецЦикла;
    
    Возврат МассивXML;
    
КонецФункции

CREATE FUNCTION dbo.get_TableFromXmlArrayOfId(@xmlArray xml)
RETURNS TABLE
AS
RETURN
(
    SELECT xmlArray.id.value('@e','int') AS id
    FROM   @xmlArray.nodes('/a[@e]') xmlArray(id)
)
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший