|
выполнить функцию MSSQL с помощью SQL-DMO | ☑ | ||
---|---|---|---|---|
0
avz07
09.08.13
✎
16:33
|
я раньше написал функцию в Microsoft SQL Server Management Studio. теперь хочу ее код с 1С передать на выполнение в SQL и получить результат. все организовать хочу через sql-dmo. но у меня не получается.
Пожалуйста, помогите мне пожалуйста. вот функция: CREATE FUNCTION RES_PO_POLYU() RETURNS int BEGIN DECLARE @RES int IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') SET @RES=1; ELSE SET @RES=0; RETURN @RES END GO |
|||
1
Jaap Vduul
09.08.13
✎
16:39
|
||||
2
avz07
09.08.13
✎
16:55
|
если я правильно понял, должно быть так:
СКЛ = Новый COMObject ("SQLDMO.SQLServer"); СКЛ.Connect("10.133.100.5","1c_base","1c_base"); СтрокаПровSQL="CREATE FUNCTION RES_PO_POLYU() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN @RES |END |GO"; RSProv=СКЛ.Databases(Строка(БД)).ExecuteWithResults(СтрокаПровSQL); .ExecuteWithResultsAndMessages2(СтрокаПровSQL ,Messages) asQueryResults а параметр без изменений Messages,или здесь должна быть переменная которую возвращает функция? |
|||
3
avz07
09.08.13
✎
16:56
|
извиняюсь
RSProv=СКЛ.Databases(Строка(БД)).ExecuteWithResultsAndMessages2(СтрокаПровSQL ,Messages) asQueryResults; . |
|||
4
Новенький_2009
09.08.13
✎
17:06
|
а не проще саму функцию в базе создать, и обычным запросом получить резалт?
|
|||
5
avz07
09.08.13
✎
17:13
|
это пример на тестовой базе.
есть бага бд по которым надо выполнять время от времени эту функцию |
|||
6
Новенький_2009
09.08.13
✎
17:58
|
Был у меня пример где-то. Я тоже ёпся долго ;) Если найду - кину. Но я через ADO делал.
|
|||
7
avz07
09.08.13
✎
18:13
|
И от ADO не откажусь. Буду очень и очень благодарен!
|
|||
8
МихаилМ
09.08.13
✎
19:03
|
SQLDMO с мс скл 2008 не поддерживается. теперь rdo
|
|||
9
avz07
09.08.13
✎
19:29
|
если через RDO, то как осуществить подключение?
|
|||
10
etc
09.08.13
✎
20:54
|
не проще ли через ADO подсоединиться и сделать что-то типа:
ADOConnection.Execute("CREATE FUNCTION RES_PO_POLYU() ... |
|||
11
avz07
10.08.13
✎
09:33
|
попытался так:
СтрокаСоединение="Provider=SQLOLEDB.1; |Password=***; |Persist Security Info=True; |User ID=*** ; |Initial Catalog="+***+"; |Data Source=*****;"; Соединение = Новый COMОбъект("ADODB.Connection"); Соединение.Open(СтрокаСоединение); Команда = Новый COMОбъект("ADODB.Command"); Команда.CommandTimeOut = 150000; Команда.NamedParameters = True; Команда.CommandType =1; Команда.ActiveConnection = Соединение; Команда.CommandText="CREATE FUNCTION RES_PO_POLYU() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN @RES |END GO"; RSProv=Новый COMОбъект("ADODB.Recordset"); RSProv=Команда.Execute(); RSProv.MoveFirst(); и мне выдало ошибку: {Форма.Форма.Форма(2152)}: Ошибка при вызове метода контекста (Execute) RSProv=Команда.Execute(); по причине: Произошла исключительная ситуация (Microsoft OLE DB Provider for SQL Server): Incorrect syntax near 'GO'. в SQL эта функция работает хорошо.не могу понять, почему системе не воспринимает оператор GO?? |
|||
12
oleg_km
10.08.13
✎
09:44
|
(11) Потому что GO Это не оператор T-SQL, это оператор QA. Смело выкидываейте его и все будет работать
|
|||
13
avz07
10.08.13
✎
09:58
|
удалил GO и заработало. но когда второй раз выполнил код мне выдало ошибку:
{Форма.Форма.Форма(2152)}: Ошибка при вызове метода контекста (Execute) RSProv=Команда.Execute(); по причине: Произошла исключительная ситуация (Microsoft OLE DB Provider for SQL Server): There is already an object named 'RES_PO_POLYU' in the database. как выполнять эту функцию повторно? возможно удалять ее после выполнения? |
|||
14
ДенисЧ
10.08.13
✎
10:01
|
дык проверяй на наличие перед созданием...
|
|||
15
avz07
10.08.13
✎
10:10
|
и если такая уже существует то удалять или повторить выполнение уже существующей?
|
|||
16
ДенисЧ
10.08.13
✎
10:13
|
(15) это уже тебе решать :-)
Я бы вообще фуннкцией для такого запроса не заморачивался... |
|||
17
etc
10.08.13
✎
14:24
|
только можно было проще:
Соединение = Новый COMОбъект("ADODB.Connection"); Соединение.Open(СтрокаСоединение); Соединение.Execute("CREATE FUNCTION RES_PO_POLYU() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN @RES |END GO"); |
|||
18
avz07
15.08.13
✎
16:25
|
спасибо, но к сожалению так не подойдет, потому что без оператора GO пакет не передаст на исполнение..а этот GO вообще есть возможность заменить или что-то в этом роде??
|
|||
19
ДенисЧ
15.08.13
✎
16:28
|
(18) "без оператора GO пакет не передаст на исполнение"
Слушай... Поделись рецептиком.. Что такое забористое ты выпил? |
|||
20
avz07
15.08.13
✎
17:39
|
я чего-то не совсем понимаю в материале ...?
|
|||
21
avz07
15.08.13
✎
17:43
|
Соединение = Новый COMОбъект("ADODB.Connection"); Соединение.Open(СтрокаСоединение); Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL
|DROP FUNCTION dbo.REZ; //|GO |CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END"); |
|||
22
avz07
15.08.13
✎
17:46
|
как тут без GO?
|
|||
23
avz07
15.08.13
✎
18:00
|
а если с GO, то вот такая ошибка:
{Форма.Форма.Форма(2136)}: Ошибка при вызове метода контекста (Execute) Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL по причине: Произошла исключительная ситуация (Microsoft OLE DB Provider for SQL Server): Incorrect syntax near 'GO'. |
|||
24
Зойч
15.08.13
✎
18:02
|
(22) какая ошибка без го?
|
|||
25
avz07
15.08.13
✎
18:05
|
{Форма.Форма.Форма(2136)}: Ошибка при вызове метода контекста (Execute)
Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL по причине: Произошла исключительная ситуация (Microsoft OLE DB Provider for SQL Server): 'CREATE FUNCTION' must be the first statement in a query batch. |
|||
26
avz07
15.08.13
✎
18:06
|
возможно я неверно написал, возможно чего-то не знаю, не понимаю хорошо. подскажите или сбросьте какую-то литературу где такая ситуация описана.
|
|||
27
avz07
15.08.13
✎
19:56
|
а может через TADODataSet?
|
|||
28
etc
15.08.13
✎
20:49
|
раздели на 2 execut_а:
Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL DROP FUNCTION dbo.REZ;"); Соединение.Execute("CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END"); |
|||
29
etc
15.08.13
✎
20:51
|
"GO — это не инструкция Transact-SQL; это команда, распознаваемая программами sqlcmd и osql, а также редактором кода среды Среда SQL Server Management Studio.
Программы SQL Server интерпретируют команду GO как сигнал о том, что им следует отправить текущий пакет инструкций Transact-SQL экземпляру SQL Server." ... "потому что гладиолус" |
|||
30
avz07
15.08.13
✎
21:03
|
спасибо за помощь!
я к этому дочитался. Но если разделить на две части, не увеличится ли время выполнения? |
|||
31
etc
15.08.13
✎
21:12
|
Даже если бы это увеличивало время выполнения на пару секунд, у тебя что создание функции самая часто используеая операция? Наверняка максимум 1 раз за сессию.
|
|||
32
avz07
16.08.13
✎
11:39
|
нет. хочется, чтобы все было правильно, минимизировано.
|
|||
33
ДенисЧ
16.08.13
✎
11:40
|
(32) Один раз создавай. Она что, у тебя каждый день меняется?
|
|||
34
avz07
19.08.13
✎
12:24
|
еще один вопрос: "как вывести результат если я сделаю через два execut_а"?
|
|||
35
avz07
19.08.13
✎
12:25
|
имею в виду результат выполнения функции
|
|||
36
ДенисЧ
19.08.13
✎
12:30
|
у адодб есть возможность NextRecordset() сказать...
|
|||
37
avz07
19.08.13
✎
12:32
|
ДенисЧ, буду очень благодарен, если подскажете
|
|||
38
Serginio1
19.08.13
✎
12:32
|
РекордСет=Command.Execute();
Резулт=""; Пока РекордСет<>неопределено Цикл Если РекордСет.Fields.Count>0 Тогда Поле=РекордСет.Fields(0); Стр=Поле.Name+" "+Поле.Value; Если ЗначениеЗаполнено(Резулт) тогда Резулт=Резулт+" |"+Стр иначе Резулт=Стр; КонецЕсли; КонецЕсли; РекордСет=РекордСет.NextRecordSet(); КонецЦикла; Сообщить(Резулт); |
|||
39
avz07
19.08.13
✎
12:34
|
тоесть, после этого:
Соединение.Execute("CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END"); будет идти (38) |
|||
40
Serginio1
19.08.13
✎
12:39
|
CREATE FUNCTION dbo.REZ() тебе ничего не вернет.
Результат возвращает Select (не помню как там насчет No Count) |
|||
41
avz07
19.08.13
✎
12:44
|
да, я что-то не то написал ..
|
|||
42
avz07
19.08.13
✎
12:45
|
сначала я создаю функцию, а потом мне ее надо вызвать, чтобы она выполнилась
|
|||
43
avz07
19.08.13
✎
12:49
|
вот жаль, я не умею это делать. с ADO первый раз работать начал
|
|||
44
Serginio1
19.08.13
✎
12:57
|
Если тебе нужно единажды вызвать можешь посмотреть в сторону CTE http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
|
|||
45
avz07
19.08.13
✎
13:01
|
да. эта функция будет вызывать 1 раз, только когда будет запускаться внешняяобработка с ней
|
|||
46
avz07
19.08.13
✎
13:18
|
что-то я не совсем понял эту статью..
возможно у кого-то есть какой-то пример? |
|||
47
Serginio1
19.08.13
✎
13:29
|
||||
48
Serginio1
19.08.13
✎
15:04
|
||||
49
avz07
19.08.13
✎
16:15
|
какое отношение имеет рекурсивный запрос к моей функции?
|
|||
50
avz07
19.08.13
✎
16:17
|
вот что у меня получилось, но это не отражает результат:
СтрокаСоединение="Provider=SQLOLEDB.1; |Password=1c_base; |Persist Security Info=True; |User ID=1c_base ; |Initial Catalog="+БД+"; |Data Source=10.133.100.5;"; Соединение = Новый COMОбъект("ADODB.Connection"); Соединение.Open(СтрокаСоединение); Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL DROP FUNCTION dbo.REZ;"); Соединение.Execute("CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END"); CMD = Новый COMОбъект("ADODB.Command"); CMD.ActiveConnection = Соединение; CMD.CommandText="dbo.REZ"; RecordSet=Новый COMОбъект("ADODB.Recordset"); RecordSet=CMD.Execute(); Результ=""; Пока RecordSet<>Неопределено Цикл Если RecordSet.Fields.Count>0 Тогда Поле=RecordSet.Fields(0); Стр=Поле.Name+" "+Поле.Value; Если ЗначениеЗаполнено(Результ) Тогда Результ=Результ+""+Стр Иначе Результ=Стр; КонецЕсли; КонецЕсли; RecordSet=RecordSet.NextRecordSet(); КонецЦикла; Сообщить(Результ); |
|||
51
Serginio1
19.08.13
✎
16:23
|
А где "Select dbo.REZ as Result"
|
|||
52
Serginio1
19.08.13
✎
16:24
|
"Select dbo.REZ() as Result"
|
|||
53
Serginio1
19.08.13
✎
16:28
|
И тебе не нужен NextRecordSet(); он нужен когда вызываются несколько Select
Проще использовать такой синтаксис Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NULL |Begin |CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END End"); или разделять запросы через ; |
|||
54
avz07
19.08.13
✎
18:51
|
за (52) огромное спасибо!
|
|||
55
avz07
19.08.13
✎
18:54
|
попытался модифицировать код скл и столкнулся с той же ошибкой: не уникальное имя функции в пакете. вот код:
IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL BEGIN DROP FUNCTION dbo.REZ; END ELSE BEGIN CREATE FUNCTION dbo.REZ() RETURNS int BEGIN DECLARE @RES int IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') SET @RES=1; ELSE SET @RES=0; RETURN(@RES); END END |
|||
56
Serginio1
20.08.13
✎
10:27
|
(55) Ну дык
IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL BEGIN DROP FUNCTION dbo.REZ; END; CREATE FUNCTION dbo.REZ() RETURNS int BEGIN DECLARE @RES int IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') SET @RES=1; ELSE SET @RES=0; RETURN(@RES); END; |
|||
57
avz07
20.08.13
✎
15:38
|
Serginiol, большое спасибо за Вашу помощь! Я и так, как вы мне сбросили, пробовал делать. К сожалению ошибка все та же..
|
|||
58
Serginio1
20.08.13
✎
15:53
|
Смотрим http://msdn.microsoft.com/ru-ru/library/ms186755.aspx
такая конструкция должна работать IF OBJECT_ID (N'dbo.REZ', N'FN') IS NOT NULL DROP FUNCTION dbo.REZ; CREATE FUNCTION dbo.REZ() http://msdn.microsoft.com/ru-ru/library/ms190324.aspx FN = скалярная функция SQL Для проверки сделай запрос Select OBJECT_ID (N'dbo.REZ', N'FN') |
|||
59
Ёпрст
20.08.13
✎
15:57
|
(58) не будет
|
|||
60
Ёпрст
20.08.13
✎
15:57
|
работать
|
|||
61
avz07
20.08.13
✎
16:17
|
да, такая конструкция работает, но с переключателем GO, который информирует об окончании пакета иструкций. А в пакете инструкций, имя функции должно быть уникальное (без повторений). Эту уникальность обеспечивал переключатель GO.
разве что ADO интерпретирует его самостоятельно. Потому, что в СКЛ так работать не будет. |
|||
62
Ёпрст
20.08.13
✎
16:20
|
(61) чего-й то ты всё перепутал
|
|||
63
avz07
20.08.13
✎
16:22
|
(58), я читал эти статьи.
Возможно я что-то пропустил. но будто правельно все сделал и в Менеджере СКЛ, когда пробовал все пахало. А когда начал подстраиваться под 1С, то возникли трудности. |
|||
64
Serginio1
20.08.13
✎
16:50
|
(59) а так
DECLARE @RES int; IF OBJECT_ID (N'dbo.REZ', N'FN') IS NOT NULL SET @RES=1; ELSE SET @RES=0; Select @RES as СуществуетФункция; |
|||
65
Serginio1
20.08.13
✎
16:54
|
(63) У меня такие конструкции
Стр=" |BEGIN TRAN; |If OBJECT_ID('TempDB.dbo.#TempPrice') is not NULL DROP TABLE #TempPrice; |Declare @ТекущаяДата as datetime= GetDate() прекрасно работают. В пакетном запросе операторы разделяются ; |
|||
66
Ёпрст
20.08.13
✎
16:55
|
автору надо просто делать как в (28) и привет..
т.е делать отдельными запросами дроп и креайт функции .. и усё. |
|||
67
Serginio1
20.08.13
✎
17:19
|
(66) Можно и так, только можно и в одно пакетном запросе. Просто на семерке в 1с++ приходится включать
set nocount on ТекстЗапроса=" |set nocount on |if exists (select * from tempdb..sysobjects where id=object_id('tempdb..%Имя%') and sysstat & 0xf = 3 ) | drop table %Имя%; |"+СтрCreate+" |set nocount off |"; рс_=СоздатьОбъект("ODBCRecordset"); рс_.УстБД(ИБ); рс_.ВыполнитьИнструкцию(СтрЗаменить(ТекстЗапроса,"%Имя%",ИмяТаб)); рс.Подготовить(СтрЗаменить(СтрInsert,"%Имя%",ИмяТаб)); рс.ВыполнитьSQL_ИзТЗ(ТЗ,100); |
|||
68
Ёпрст
20.08.13
✎
17:26
|
(67) да нет пакета в адо
|
|||
69
Ёпрст
20.08.13
✎
17:26
|
вот и ошибки у него валются..
|
|||
70
Serginio1
20.08.13
✎
17:29
|
(68) Есть возможность выполнения нескольких операторов разделенных точкой с запятой. А вот откуда у него ошибки это вопрос и какой у него MS SQL
|
|||
71
Serginio1
20.08.13
✎
17:50
|
По set nocount on разобрался
http://www.sql.ru/forum/2652/ispolnenie-skripta-iz-adodb-mozhet-i-off В ADO Insert возвращает recordset если set nocount off |
|||
72
avz07
20.08.13
✎
18:20
|
MS SQL 2008, не R2
|
|||
73
avz07
20.08.13
✎
18:25
|
вот что сделал я:
СтрокаСоединение="Provider=SQLOLEDB.1; |Password=1c_base; |Persist Security Info=True; |User ID=1c_base ; |Initial Catalog="+БД+"; |Data Source=10.133.100.5;"; Соединение = Новый COMОбъект("ADODB.Connection"); Соединение.Open(СтрокаСоединение); Соединение.Execute("IF OBJECT_ID(N'dbo.REZ',N'FN')IS NOT NULL DROP FUNCTION dbo.REZ;"); Соединение.Execute("CREATE FUNCTION dbo.REZ() |RETURNS int |BEGIN |DECLARE @RES int |IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='kod_1c') |SET @RES=1; |ELSE |SET @RES=0; |RETURN(@RES); |END"); CMD = Новый COMОбъект("ADODB.Command"); CMD.ActiveConnection = Соединение; CMD.CommandText="SELECT dbo.REZ() AS Result"; RecordSet=Новый COMОбъект("ADODB.Recordset"); RecordSet=CMD.Execute(); Результ=""; Если RecordSet.Fields.Count>0 Тогда Поле=RecordSet.Fields(0); Стр=Поле.Value; Если ЗначениеЗаполнено(Результ) Тогда Результ=Результ+""+Стр Иначе Результ=Стр; КонецЕсли; КонецЕсли; |
|||
74
Serginio1
20.08.13
✎
18:29
|
А 56 что выдает?
|
|||
75
avz07
20.08.13
✎
18:44
|
в 1С пишет что ошибка метода Execute по причине:произошло исключительная ситуация...
А Менеджер СКЛ видает такое: Сообщение 111, уровень 15, состояние 1, строка 6 'CREATE FUNCTION' must be the first statement in a query batch. Сообщение 178, уровень 15, состояние 1, строка 14 A RETURN statement with a return value cannot be used in this context. подчеркивает CREATE FUNCTION dbo.REZ() |
|||
76
avz07
20.08.13
✎
18:49
|
обидно что мне не получается написать все одним пакетом, но надо сдать задание ..
если кто-то посоветует еще что-небуть, буду сердечно благодарен. а так, всем спасибо за участие в обсуждении! |
|||
77
Serginio1
20.08.13
✎
18:59
|
Да смутно припоминаю на ограничения для функций, что они дожны быть первыми в пакетном запросе. Так, что ничего страшного.
|
|||
78
avz07
20.08.13
✎
19:01
|
Serginio1, вам отдельное спасибо за активное участие и помощь!
|
|||
79
Serginio1
21.08.13
✎
10:25
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |