remedius
Гость
|
|
« : 18-11-2006 15:12 » |
|
Доброго времени суток! Если кто имел дело с sql api, есть ли возможность получить значение, возвращаемое из хранимой процедуры по return? Если да, то каким образом это можно сделать? 2.Можно ли передать аргументы для хранимой процедуры в строке setCommandText?(у меня что-то не получается .Приходится устнавливать вручную через CreateParam. Спасибо.
|
|
« Последнее редактирование: 12-12-2006 20:26 от remedius »
|
Записан
|
|
|
|
Oldy
|
|
« Ответ #1 : 18-11-2006 15:18 » |
|
select mystoredproc(par1, par2 ...) - не работает?
|
|
|
Записан
|
С уважением, Oldy.
|
|
|
remedius
Гость
|
|
« Ответ #2 : 18-11-2006 15:20 » |
|
т.е. вместо pCmd.setCommandText("sp_alter_table",SA_CmdStoredProc ); указывать что-то типа ("select mystoredproc(par1, par2 ...)",...); ?
|
|
|
Записан
|
|
|
|
Oldy
|
|
« Ответ #3 : 18-11-2006 15:39 » |
|
Ну да, разве иначе можно получить возвращаемые данные? Потом ALTER TABLE - DDL команда, а я понял из вопроса, что нужна DML. Т.е. нужно получить данные, а не изменять структуру таблицы.
|
|
|
Записан
|
С уважением, Oldy.
|
|
|
remedius
Гость
|
|
« Ответ #4 : 18-11-2006 15:45 » |
|
pCmd.setCommandText("SELECT sp_create_spacial_index (:1)",SA_CmdSQLStmt); pCmd.Param(1).setAsString() = sTblName; Вот так не работает: 'sp_create_spacial_index' is not a recognized function name.
|
|
« Последнее редактирование: 15-12-2007 20:15 от Алексей1153++ »
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #5 : 20-11-2006 19:06 » |
|
А что за язык программирования используется и СУБД? Собрал тут коротенький пример: серверная часть на SQL Server 2000 (язык T-SQL) и клиент WSH 5.6 (язык VBScript + библиотека ADO 2.8 ). В начале создаём экспериментальную БД: EXEC sp_addlogin @loginame = 'TestLogin', @passwd = 'TestPassword'
CREATE DATABASE Test GO
USE Test GO
EXEC sp_adduser @loginame = 'TestLogin', @name_in_db = 'TestUser'
CREATE PROCEDURE spTest @Param VARCHAR(10) AS IF @Param = 'Zero' RETURN 0 ELSE RETURN 1 GO
GRANT EXECUTE ON spTest TO TestUser Затем пишем клиента: ' Файл test.vbs On Error Resume Next
Dim Connection
' Открываем Set Connection = CreateObject("ADODB.Connection") Connection.ConnectionString = _ "Provider=SQLOLEDB.1;" & _ "User ID=TestLogin;" & _ "Password=TestPassword;" & _ "Data Source=TESTSERVER;" & _ "Initial Catalog=Test;" Call Connection.Open If Err.number <> 0 Then Call WScript.Echo("Отсутствие соединения: " & Err.Description) Stop End If
' Тестируем Call WScript.Echo("Проверка с Zero - возвращённое значение: " & CommandExecute(Connection, "Zero")) Call WScript.Echo("Проверка с Nonzero - возвращённое значение: " & CommandExecute(Connection, "Nonzero"))
' Закрываем Call Connection.Close
Set Connection = Nothing
' Тестовая функция Function CommandExecute(Connection, Param) Dim Command, I, Value
' Настраиваем Set Command = CreateObject("ADODB.Command") Set Command.ActiveConnection = Connection Command.CommandType = 4 ' adCmdStoredProc = 4 Command.CommandText = "spTest" ' Второй параметр: adInteger = 3, adVarChar = 200 ' Третий параметр: adParamInput = 1, adParamReturnValue = 4 Call Command.Parameters.Append(Command.CreateParameter(, 3, 4)) Call Command.Parameters.Append(Command.CreateParameter("@Param", 200, 1, 10, Param))
' Обращаемся к серверу Call Command.Execute If Err.number <> 0 Then Call WScript.Echo("Ошибка исполнения команды: " & Err.Description) Call Err.Clear CommandExecute = "Ошибка" Exit Function End If ' Обрабатываем параметры и вычисляем результат Call Command.Parameters.Refresh If IsEmpty(Command.Parameters(0).Value) Then Value = "Empty" Else Value = Command.Parameters(0).Value End If CommandExecute = Command.Parameters(0).Name & " = " & Value Set Command = Nothing End Function Откуда следует, что для получения возврщаемого хранимой процедурой результата надлежит добавить в коллекцию параметров на первое место целочисленный параметр типа adParamReturnValue (числовое значение 4). После выполнения команды коллекцию параметров нужно обновить и прочитать значение введённого параметра. Проверяем работу: C:\>cscript test.vbs Сервер сценариев Windows (Microsoft R) версия 5.6 c Корпорация Майкрософт (Microsoft Corp.), 1996-2001. Все права защищены.
Проверка с Zero - возвращённое значение: @RETURN_VALUE = 0 Проверка с Nonzero - возвращённое значение: @RETURN_VALUE = 1
Работает! Удаляем за собой на сервере: USE master GO
DROP DATABASE Test
EXEC sp_droplogin @loginame = 'TestUser' P.S. Естественно, речь идёт о SQL Server, а не о произвольной СУБД.
|
|
« Последнее редактирование: 15-12-2007 20:16 от Алексей1153++ »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #6 : 20-11-2006 19:15 » |
|
dimka, Извиняюсь - не поняла про что Вы написали. Используется sql api библиотека
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #7 : 20-11-2006 19:19 » |
|
есть ли возможность получить значение, возвращаемое из хранимой процедуры по return? Если да, то каким образом это можно сделать? Повторяю: завести параметр типа ReturnValue, целочисленный; поместить его первым в коллекции параметров. Не работает?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #8 : 20-11-2006 19:20 » |
|
все, поняла. Проверю. P.S. вообще-то заводила, но не додумалась его первым заводить:( Спасибо
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #9 : 20-11-2006 19:34 » |
|
Ещё, кстати, полезно обратить внимание на такой момент: http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q194792Хотя, наверно, в последнее время это уже не так актуально.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #10 : 20-11-2006 19:57 » |
|
Вот работающий вариант. pCmd.setCommandText("sp_create_spacial_index",SA_CmdStoredProc ) pCmd.CreateParam("",SA_dtLong, -1, 4,0,0,SA_ParamReturn); T = ExecuteCommand(&pCmd); printf("Result: %i\n",pCmd.ParamByIndex(0).asLong()); Спасибо dimka! Получается еще, что нельзя прямо в setCommandText (типа "sp_create_spacial_index :1")указывать параметры, как в запросе - а жаль.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #11 : 20-11-2006 20:36 » |
|
Получается еще, что нельзя прямо в setCommandText (типа "sp_create_spacial_index :1")указывать параметры, как в запросе - а жаль. Почему это нельзя? Нужно только тип команды использовать CmdText, а не CmdStoredProc В случае явного задания параметров будет Command.CommandText = "EXEC spTest @Param = 'Zero'". Недостаток заключается в том, что значения параметров нужно задавать прямо в строке, а не в коллекции параметров. В случае неявного задания параметров будет Command.CommandText = "EXEC spTest 'Zero'". Недостаток тот же + необходимо строго соблюдать порядок следования параметров. В случае использования коллекции параметров можно использовать символы-заменители Command.CommandText = "EXEC spTest ?" и Command.Parameters(0).Value = "Zero". Недостаток в строгом порядке следования параметров. Способ обращения к SQL Server значения не имеет: это может быть и SQL API, и библиотеки вроде ADO или ADO.NET, и HTTP-запросы через ISAPI-расширение IIS и т.д., и т.п. Суть и правила работы от этого не меняются. Разница только в конкретных названиях объектов, методов, свойств и констант и синтаксисе используемого языка программирования.
|
|
« Последнее редактирование: 15-12-2007 20:16 от Алексей1153++ »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #12 : 20-11-2006 21:05 » |
|
dimka, Да вот так работает: pCmd.setCommandText("EXEC sp_create_spacial_index :1, :2 ",SA_CmdSQLStmt), но это в случае, гогда не указываешь параметр возврата. Что-то типа "SET :1 =EXECT (SELECT) sp_create_spacial_index :2, :3" - ошибка.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #13 : 21-11-2006 09:12 » |
|
Что-то типа "SET :1 =EXECT (SELECT) sp_create_spacial_index :2, :3" - ошибка. Да, так не работает. Вообще говоря, правильный синтаксис тогда уж: "EXEC :1 = sp_create_spacial_index :2, :3" (см BOL).
|
|
« Последнее редактирование: 21-11-2006 09:15 от dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #14 : 21-11-2006 09:27 » |
|
Вы наверняка правы с синтаксисом, но так тоже не работает: Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #15 : 21-11-2006 12:16 » |
|
но так тоже не работает: Не могу с этим согласиться, ибо факты говорят об обратном. Взята учебная база данных Northwind из поставки SQL Server, в ней взята первая попавшаяся хранимая процедура. Клиент написан на VBA в виде макроса к MS Word с подключением к макросу библиотеки ADO 2.8. Sub Test() ' Using Microsoft ActiveX Data Objects 2.8 Library On Error Resume Next Dim Connection As New ADODB.Connection With Connection .ConnectionString = _ "Provider=SQLOLEDB.1;" & _ "Integrated Security=SSPI;" & _ "Data Source=TESTSERVER;" & _ "Initial Catalog=Northwind;" Call .Open End With With Err If .Number <> 0 Then Call MsgBox("Connection error: " & .Description) Call .Clear Exit Sub End If End With Dim Command As New ADODB.Command With Command Set .ActiveConnection = Connection .CommandType = adCmdText .CommandText = "EXEC ? = CustOrderHist ?" With .Parameters(0) .Direction = adParamReturnValue .Type = adInteger .Value = -1 ' Other than 0, stored procedure must return 0. End With With .Parameters(1) .Direction = adParamInput .Type = adWChar .Size = 5 .Value = "ALFKI" End With End With Dim Recordset As ADODB.Recordset Set Recordset = Command.Execute With Err If .Number <> 0 Then Call MsgBox("Execution error: " & Err.Description) Call .Clear Exit Sub End If End With Dim Message As String Message = "" ' Data processing Dim Count As Integer Count = 0 While Not Recordset.EOF Count = Count + 1 Call Recordset.MoveNext Wend Message = Message & "Has processed " & CStr(Count) & " records." & Chr(13) Call Recordset.Close Set Recordset = Nothing Call Command.Parameters.Refresh With Command.Parameters(0) Message = Message & "Result is " & .Name & " = " & CStr(.Value) End With Set Command = Nothing Call Connection.Close Set Connection = Nothing Call MsgBox(Message) End Sub Результат работы: --------------------------- Microsoft Word --------------------------- Has processed 11 records. Result is @RETURN_VALUE = 0 --------------------------- ОК ---------------------------
Результат работы хранимой процедуры получен. Результат верный - 0, хотя предварительно параметр был установлен в -1. Кроме того, всё же работает та синтаксическая конструкция, которая, по вашим словам, не работает. Ошибка "Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.", видимо, имеет номер 80004005 - "Подключение занято выдачей результатов для другой команды" и связана с тем, что вы пытались получить результат, предварительно не закрыв полученный Recordset. Обратите внимание на порядок выполняемых вами действий, ибо работа прикладного программиста сродни работе сапёра .
|
|
« Последнее редактирование: 15-12-2007 20:17 от Алексей1153++ »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #16 : 22-11-2006 16:57 » |
|
dimka, Честно говоря, не совсем понимаю о каком RecordSet Вы говорите: Вот так работает: pCmd.setCommandText("EXEC sp_create_spacial_index :1, :2 ",SA_CmdSQLStmt); pCmd.Param(1).setAsString() = sTblName; pCmd.Param(2).setAsNull(); ExecuteCommand(&pCmd); pCmd.DestroyParams();
Вот так нет: pCmd.setCommandText("EXEC :1 = sp_create_spacial_index :2, :3 ",SA_CmdSQLStmt); pCmd.Param(1).setAsLong(); pCmd.Param(2).setAsString() = sTblName; pCmd.Param(3).setAsNull(); ExecuteCommand(&pCmd); pCmd.DestroyParams();
По моему здесь опять дело в синтаксисе:(
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #17 : 22-11-2006 17:59 » |
|
По моему здесь опять дело в синтаксисе:( Не думаю. pCmd.Param(1).setAsLong();
Тип данных параметра вы задали - хорошо. А где тип самого параметра? По умолчанию параметр рассматривается как Input, а вам надо ReturnValue. Где эта настройка? Не вижу.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
remedius
Гость
|
|
« Ответ #18 : 22-11-2006 18:03 » |
|
На самом деле я об этом тоже думала, и даже пробовала:) pCmd.Param(1).setParamDirType(SA_ParamReturn); Но ошибка менялась на "Unknown Data Type"
|
|
|
Записан
|
|
|
|
remedius
Гость
|
|
« Ответ #19 : 22-11-2006 18:48 » |
|
Оказалось дело вот в чем: pCmd.Param(1).setParamType(SA_dtLong); Вот так все ок. А вот так: pCmd.Param(1).setAsLong(); - возникают проблемы в данном случае.
|
|
|
Записан
|
|
|
|
remedius
Гость
|
|
« Ответ #20 : 22-11-2006 18:51 » |
|
Все больше и больше я начинаю понимать - НАДО ЧИТАТЬ МАНУАЛ!
Спасибо
|
|
|
Записан
|
|
|
|
|