Имя: Пароль:
1C
1С v8
Пустой результат запроса MS SQL
,
0 Amfiaray
 
27.10.17
08:11
Добрый день!
Делаю запрос к базе MS SQL, вот код:

Подключение = Новый ComObject("ADODB.Connection");
Подключение.ConnectionString="SERVER="+Сервер+"; Database="+База+"; DRIVER=SQL Server; UID="+ИмяПользователя+"; PWD="+Пароль+";";
Попытка
    Подключение.Open();
Исключение
    Сообщить(ОписаниеОшибки());
    Возврат Ложь;
КонецПопытки;

СоединениеSQL = Новый COMObject("ADODB.Command");
СоединениеSQL.ActiveConnection = Подключение;
СоединениеSQL.CommandText = "use [Traffic]
            |select DISTINCT ReferenceID from vRefDocuments RD
            |inner join vFactHistory FH ON FH.HistoryDocId = RD.ReferenceId
            |inner join vFactTransport FT ON FT.FactHistoryId = FH.FactHistoryId AND FT.FactSource = 909237
            |where RD.DocTypeId = 1041302 and
            |      FT.CreateDate between convert(datetime, '"+Формат(НачалоДня(ДатаНачала), "ДФ='yyyy-MM-dd'")+" 00:00:00'"+", 120) and convert(datetime, '"+Формат(КонецДня(ДатаОкончания), "ДФ='yyyy-MM-dd'")+" 23:59:59'"+", 120)
            |      and FT.DeletedFlag <> 1";
СоединениеSQL.CommandType = 1;
ЗаписиSQL = Новый ComObject("ADODB.RecordSet");
Попытка
    ЗаписиSQL = СоединениеSQL.Execute();
Исключение
    Сообщить(ОписаниеОшибки());
    Подключение.Close();
    Возврат Ложь;
КонецПопытки;

Запрос отрабатывает без ошибок, но результат запроса пустой. Этот же текст запроса при выполнении в Management Studio выдает нормальный результат, не пустой.
Подскажите как правильно сделать прямой запрос к SQL?
1 бомболюк
 
27.10.17
08:15
дело в датах наверное
2 бомболюк
 
27.10.17
08:17
сравнивай просто со строками вида '20171027'
3 Amfiaray
 
27.10.17
08:17
(1) А что с датами не так? Для проверки ставил точку останова. брал текст запроса из СоединениеSQL.CommandText и выполнял его в Management Studio, результат был нормальный.
4 бомболюк
 
27.10.17
08:22
(3) а просто больше сюрпризов тут ждать неоткуда.
5 Amfiaray
 
27.10.17
08:26
(4) Не прокатило, результат тот же.
Может я выборку как то не правильно обхожу?

Вот код по заполнению ТЗ

Таблица = Новый ТаблицаЗначений;
Для НомерСтолбца = 0 По ЗаписиSQL.Fields.Count-1 Цикл
        ИмяСтолбца =ЗаписиSQL.Fields.Item(НомерСтолбца).Name;
       Таблица.Колонки.Добавить(ИмяСтолбца);
КонецЦикла;


Пока ЗаписиSQL.EOF = 0 Цикл
    НоваяСтрока =  Таблица.Добавить();
        Для НомерСтолбца = 0 По ЗаписиSQL.Fields.Count-1 Цикл
            НоваяСтрока.Установить(НомерСтолбца,ЗаписиSQL.Fields(НомерСтолбца).Value);
        КонецЦикла;
    ЗаписиSQL.MoveNext();
КонецЦикла;

ЗаписиSQL.Close();
Подключение.Close();
Возврат Таблица;

Колонка в таблицу добавляется, а строки нет.
6 бомболюк
 
27.10.17
08:32
тут все верно
7 бомболюк
 
27.10.17
08:33
покажи новый код
8 Amfiaray
 
27.10.17
08:40
Подключение = Новый ComObject("ADODB.Connection");
Подключение.ConnectionString="SERVER="+Сервер+"; Database="+База+"; DRIVER=SQL Server; UID="+ИмяПользователя+"; PWD="+Пароль+";";
Попытка
    Подключение.Open();
Исключение
    Сообщить(ОписаниеОшибки());
    Возврат Ложь;
КонецПопытки;

СоединениеSQL = Новый COMObject("ADODB.Command");
СоединениеSQL.ActiveConnection = Подключение;
СоединениеSQL.CommandText = "use [Traffic]
            |select DISTINCT ReferenceID from vRefDocuments RD
            |inner join vFactHistory FH ON FH.HistoryDocId = RD.ReferenceId
            |inner join vFactTransport FT ON FT.FactHistoryId = FH.FactHistoryId AND FT.FactSource = 909237
            |where RD.DocTypeId = 1041302 and
            |      FT.CreateDate between convert(datetime, '"+Формат(НачалоДня(ДатаНачала), "ДФ='yyyyMMdd'")+"'"+", 120) and convert(datetime, '"+Формат(КонецДня(ДатаОкончания), "ДФ='yyyyMMdd'")+"'"+", 120)
            |      and FT.DeletedFlag <> 1";
СоединениеSQL.CommandType = 1;

ЗаписиSQL = Новый ComObject("ADODB.RecordSet");
Попытка
       ЗаписиSQL = СоединениеSQL.Execute();
Исключение
    Сообщить(ОписаниеОшибки());
    Подключение.Close();
    Возврат Ложь;
КонецПопытки;    

Таблица = Новый ТаблицаЗначений;
Для НомерСтолбца = 0 По ЗаписиSQL.Fields.Count-1 Цикл
        ИмяСтолбца =ЗаписиSQL.Fields.Item(НомерСтолбца).Name;
        Таблица.Колонки.Добавить(ИмяСтолбца);
КонецЦикла;

Пока ЗаписиSQL.EOF = 0 Цикл
    НоваяСтрока =  Таблица.Добавить();
      Для НомерСтолбца = 0 По ЗаписиSQL.Fields.Count-1 Цикл
            НоваяСтрока.Установить(НомерСтолбца,ЗаписиSQL.Fields(НомерСтолбца).Value);
        КонецЦикла;
    ЗаписиSQL.MoveNext();
КонецЦикла;

ЗаписиSQL.Close();
Подключение.Close();
Возврат Таблица;
9 1c_July
 
27.10.17
08:48
извините, что влезаю, хоть не совсем в теме, но возникли идеи: может какой-нибудь MoveFirst перед циклом?
(если по аналогии execute - "выполнить", а потом еще надо "выбрать" - перед тем как ходить по записям в цикле)
И еще попробовать ЗаписиSQL.count проверить.
10 бомболюк
 
27.10.17
08:51
я предполагал ты мне нормальный текст запроса тут засветишь, безо всяких склеек. давай просто захардкодим:
           |      FT.CreateDate >= '20171001' and FT.CreateDate < '20171028'
11 Amfiaray
 
27.10.17
08:57
(9) MoveFirst() выдал ошибку:
Произошла исключительная ситуация (ADODB.Recordset): BOF или EOF имеет значение True, либо текущая запись удалена. Для выполняемой операции требуется текущая запись.
12 Amfiaray
 
27.10.17
08:58
(10)С таким запросом:

use [Traffic]
select DISTINCT ReferenceID from vRefDocuments RD
inner join vFactHistory FH ON FH.HistoryDocId = RD.ReferenceId
inner join vFactTransport FT ON FT.FactHistoryId = FH.FactHistoryId AND FT.FactSource = 909237
where RD.DocTypeId = 1041302 and
      FT.CreateDate >='20170101' and FT.CreateDate <='20170131'
      and FT.DeletedFlag <> 1

Результат тоже пустой.
13 1dvd
 
27.10.17
09:00
попробуй прописать путь к базе в самом запросе
14 Amfiaray
 
27.10.17
09:00
Может быть проблема в том что в запросе используются и базовые таблицы и представления?
15 бомболюк
 
27.10.17
09:01
(12) а в Management Studio он не пустой?
16 Amfiaray
 
27.10.17
09:01
(13) а в чем разница? запрос ведь выполняется, колонки в выборки есть, а сток нет.
17 1dvd
 
27.10.17
09:01
(16) не помню. Давно занимался этим, но делал именно так
18 Amfiaray
 
27.10.17
09:02
(15) нет не пустой, 119 записей выводит
19 бомболюк
 
27.10.17
09:03
так не бывает. может базы или сервера разные в консоли и запросе из 1С?
20 Amfiaray
 
27.10.17
09:05
(19)всё одинаково.
21 Amfiaray
 
27.10.17
09:06
Пробовал добавлять эту базу как внешний источник данных, но почему то таблицы с представлениями были пустые.
22 Amfiaray
 
27.10.17
09:07
Потом добавлял хранимую процедуру с этим запросом, также в Management Studio всё отрабатывает отлично, а при вызове из 1с пусто.
23 SSSSS_AAAAA
 
27.10.17
09:09
(8)Убрать use [traffic] и добавить название базы перед таблицами. ТО есть traffic.vRefDocuments и т.д.
24 Amfiaray
 
27.10.17
09:13
(23) Не помогло, по прежнему пустой результат
25 Тихий омут
 
27.10.17
09:19
(24) чудес не бывает. отключай условия в запросе, найдёшь некорректное
26 Rokford
 
27.10.17
09:19
Может не та ситуация, но похожа. Я в свое время намучился с получением набора данных, пока не указал тип курсора. Попробуй, может поможет (именно = 3).

        ADOНаборДанных = Новый COMОбъект("ADODB.RecordSet");
        ADOНаборДанных.CursorType = 3;
        ADOНаборДанных.Open(ТекстЗапроса, ADOConnection);
27 Amfiaray
 
27.10.17
09:24
(25) Вот запрос совсем без условий:
"SELECT DISTINCT ReferenceID from [Traffic].[dbo].vRefDocuments RD
|inner join [Traffic].[dbo].vFactHistory FH ON FH.HistoryDocId = RD.ReferenceId
|inner join [Traffic].[dbo].vFactTransport FT ON FT.FactHistoryId = FH.FactHistoryId";

Результат всё равно пустой.
28 Amfiaray
 
27.10.17
09:26
(26) добавил ЗаписиSQL.CursorType = 3;
Результат так же пустой.
29 Тихий омут
 
27.10.17
09:29
(27) Двигайся дальше. Убери джойн из этой выборки - результат пустой? Если да, то не туда стучишься - не в ту базу. И вот это - [Traffic].[dbo] - мне оччень не нравится, эти вещи мне несколько лет назад (при скрещивании 7.7 и OLAP) основательно крови попили, постарайся от них избавиться - ты ведь при подключении указываешь точно имя базы, в запросе его дублировать ни к чему.
30 SSSSS_AAAAA
 
27.10.17
09:30
(18) В 1с вы что-то делаете не так, как SSMS. Потому у вас и результата нет ни одним из способов. Ищите. Не тот сервер?
31 Rokford
 
27.10.17
09:31
Почему используешь объект command а не RecordSet?
(22)Если получилось создать ХП, - попробуй вызывать ее
32 LuciferArh
 
27.10.17
09:33
(8) А почему цикл Пока ЗаписиSQL.EOF = 0 Цикл
Я бы написал
Пока НЕ ЗаписиSQL.EOF
Потому что EOF - EndOfFile, то есть достигнут конец файла, и оно булево.
33 SSSSS_AAAAA
 
27.10.17
09:33
(31) Кстати, да. Сommand для запуска ХП и подобного. Но это так, мелочи. На внешние источники данных не влияющие. И потому не главная причина.
34 Rokford
 
27.10.17
09:34
Вот из рабочей обработки функция, может поможет...

Функция ЗапросБД(ТекстЗапроса) Экспорт
    
    // соединение с MS SQL Server
    Попытка
        ADOConnection = Новый COMОбъект( "ADODB.Connection" );    
    Исключение
        ФлагОтказ = Истина;
    КонецПопытки;
    ADOConnection.Provider = "SQLOLEDB.1";
    ADOConnection.Properties( "Data Source" ).Value = СокрЛП("АААА");    //сервер;
    ADOConnection.Properties( "Initial Catalog" ).Value = СокрЛП("ББББ");  //база;
    ADOConnection.Properties( "User ID" ).Value = СокрЛП("ВВВВ");  //"uid";
    ADOConnection.Properties( "Password" ).Value = СокрЛП("ГГГГ"); //"psw";
    Попытка
        ADOConnection.Open();
    Исключение
        ФлагОтказ = Истина;
    КонецПопытки;
    // запрос
    Попытка
        ADOНаборДанных = Новый COMОбъект("ADODB.RecordSet");
        ADOНаборДанных.CursorType = 3;
        ADOНаборДанных.Open(ТекстЗапроса, ADOConnection);
    Исключение    
        ФлагОтказ = Истина;
    КонецПопытки;
    
    Таб = Новый ТаблицаЗначений;
    КоличествоПолей  = ADOНаборДанных.Fields.Count - 1;
    
    // Циклом пробегаем по всем полям в наборе данных
    // и  создаем поля в таблице значений
    Для ПолеСч = 0 по КоличествоПолей Цикл
        ИмяКолонки = ADOНаборДанных.Fields.item(ПолеСч).name;
        Если Найти(ИмяКолонки, "Дата") > 0 Тогда
            ТипКолонки = Новый ОписаниеТипов("Дата",,Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя));
        ИначеЕсли Найти(ИмяКолонки, "Количество") > 0 Тогда
            ТипКолонки = Новый ОписаниеТипов("Число",,);
        Иначе
            ТипКолонки = Новый ОписаниеТипов("Строка",,);
        КонецЕсли;
        Таб.Колонки.Добавить(ИмяКолонки, ТипКолонки, ИмяКолонки);
    КонецЦикла;
    // Заполнение таблицы значений
    Попытка
        ADOНаборДанных.MoveFirst();
    Исключение
        //Сообщение = Новый СообщениеПользователю;
        //Сообщение.Текст = "Результат запроса к SQL-серверу пустой.";
        //Сообщение.Сообщить();
        Возврат Таб;
    КонецПопытки;
    
    Счетчик = 0;
    Пока ADOНаборДанных.EOF = false Цикл
        НоваяСтрока = Таб.Добавить();
        Счетчик = Счетчик + 1;
        НоваяСтрока[0] = Счетчик;
        Для ПолеСч = 0 по КоличествоПолей Цикл
            Поле = ADOНаборДанных.Fields.item(ПолеСч);
            НоваяСтрока[ПолеСч] = СокрЛП(Формат(Поле.Value,"ЧГ=0"));
        КонецЦикла;    
        // Переходим дальше    
        ADOНаборДанных.MoveNext();
    КонецЦикла;
    
    ADOНаборДанных.Close();
    ADOConnection.Close();

    Возврат Таб;
КонецФункции // ЗапросБД()
35 Amfiaray
 
27.10.17
12:17
Спасибо, вроде разобрался с причиной проблемы, не хватает прав у пользователя SQL, только теперь не могу разобраться с правами ((
36 SSSSS_AAAAA
 
27.10.17
12:24
(35) И что с правами?
37 Amfiaray
 
27.10.17
12:55
(35) Не понятно что с правами, select на каких то таблицах нормально отрабатывает? а на каких то пустой результат№
38 бомболюк
 
27.10.17
13:07
возможно во вьюхе режется
39 SSSSS_AAAAA
 
27.10.17
13:09
(37) Ну так надо смотреть прав этого юзера на все используемые таблицы. Они ведь на каждую таблицу отдельно могут быть.
40 Yuri 83
 
27.10.17
13:15
(0) Ну смещение дат же! Прибавь пару тысяч лет.
41 Amfiaray
 
27.10.17
13:20
(39) сказал админам которые базу обслуживают чтобы с правами разобрались? а пока выпросил у них пароль от sa
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой