| 
			| 
					
						| 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.vbsOn 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 masterGO
 
 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 »  |  | 
 
 Все больше и больше я начинаю понимать - НАДО ЧИТАТЬ МАНУАЛ!
 Спасибо
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |