8

Tôi đã thiết lập một thủ tục lưu sẵn trong SQL Server hoạt động tốt. bây giờ tôi có thể gọi nó từ VBA, nhưng muốn trả về một giá trị cho biết nếu có bất kỳ lỗi nào, vv Tham số cuối cùng trong SP của tôi được thiết lập như OUTPUT:Cách trả về các giá trị từ một thủ tục lưu trữ SQL Server và sử dụng chúng trong Access VBA

@DataSetID int = 0, 
@Destination char(1)='-', 
@errStatusOK bit OUTPUT 

VBA của tôi để gọi SP dưới , nhưng nó sẽ không làm việc bây giờ, sau khi thêm các tham số mới và tôi không chắc chắn nơi tôi sẽ sai, tôi tiếp tục nhận được 3708 - Parameter object is improperly defined. Inconsistent or incomplete information was provided.:

Set cnn = New adodb.Connection 
cnn.ConnectionString = 
    "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes" 

cnn.Open cnn.ConnectionString 

Set cmd = New adodb.Command 
cmd.ActiveConnection = cnn 
cmd.CommandType = adCmdStoredProc 
cmd.CommandText = "stprMoveDataSet" 

Set param = cmd.CreateParameter 
       ("@DataSetID", adInteger, adParamInput, , stDataSet) 
cmd.Parameters.Append param 
Set param = cmd.CreateParameter 
       ("@Destination", adChar, adParamInput, 1, stDestination) 
cmd.Parameters.Append param 
Set param = cmd.CreateParameter 
       ("@errStatusOK", adBit, adParamReturnValue) 
cmd.Parameters.Append param 

rs.CursorType = adOpenStatic 
rs.CursorLocation = adUseClient 
rs.LockType = adLockOptimistic 
rs.Open cmd 

Làm thế nào tôi có thể nhận được VBA để làm việc với các OUTPUT tham số và làm cho giá trị trả về 'có thể đọc được' bởi vba.

EDIT - Tôi đã thay đổi câu hỏi để cụ thể hơn về trả về giá trị chứ không chỉ về việc sử dụng tham số OUTPUT.

Trả lời

7
Set cnn = New adodb.Connection 
cnn.ConnectionString = 
    "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes" 

cnn.Open cnn.ConnectionString 

Set cmd = New adodb.Command 
cmd.ActiveConnection = cnn 
cmd.CommandType = adCmdStoredProc 
cmd.CommandText = "stprMoveDataSet" 

Set param1 = cmd.CreateParameter 
       ("@DataSetID", adInteger, adParamInput, , stDataSet) 
cmd.Parameters.Append param 
Set param2 = cmd.CreateParameter 
       ("@Destination", adChar, adParamInput, 1, stDestination) 
cmd.Parameters.Append param 
Set param3 = cmd.CreateParameter 
       ("@errStatusOK", adBit, adParamOutput, , adParamReturnValue) 
cmd.Parameters.Append param 

rs.CursorType = adOpenStatic 
rs.CursorLocation = adUseClient 
rs.LockType = adLockOptimistic 
rs.Open cmd 
+0

Bạn phải đăng bài này trong khi tôi đã đăng câu trả lời của riêng tôi, tôi hiểu làm thế nào tôi đã đi sai với CreateParameter bây giờ. Rất cám ơn, có thể sử dụng điều đó trong tương lai. – aSystemOverload

2

Trong số các thông số khác mà từ đó "adParamInput" được lấy, khác là "adParamOutput", để chỉ ra tham số ngoài từ quy trình được lưu trữ và "adParamInputOutput" cho tham số đi "cả hai hướng" nó đã là. Trong trường hợp của bạn, tôi tin rằng "adParamOutput" sẽ phù hợp. Tôi hy vọng đây là những gì bạn đang tìm kiếm.

+0

Không phải những gì tôi đang tìm kiếm, nhưng hữu ích. Một đồng nghiệp đề nghị tôi chỉ cung cấp đầu ra thông qua một SELECT @errStatusOK vv và thao tác nó trong VBA, mà đã làm việc một điều trị. Cảm ơn – aSystemOverload

4

Ban đầu tôi đã xem các tham số OUTPUT, nhưng không thể tìm hiểu cách đưa chúng trở lại Access (trong VBA) để cung cấp phản hồi cho người dùng. Một đồng nghiệp đề nghị sử dụng một SELECT trong thủ tục được lưu trữ và sử dụng nó.

thủ tục lưu trữ: gia tăng như sau ở cuối:

SELECT @errStatusOK as errStatusOK, @countCurrent as countCurrent, @countHistorical as countHistorical 

VBA:

Dim cnn As ADODB.Connection 
Dim cmd As New ADODB.Command, rs As New ADODB.Recordset, param As New ADODB.Parameter 
Dim fld As ADODB.Field 
Dim stMessage As String 

Set cnn = New ADODB.Connection 
cnn.ConnectionString = "DRIVER=SQL Server;SERVER=SERVER\SERVER;DATABASE=a_db;Trusted_Connection=Yes" 

cnn.Open cnn.ConnectionString 

Set cmd = New ADODB.Command 
cmd.ActiveConnection = cnn 
cmd.CommandType = adCmdStoredProc 
cmd.CommandText = "stprMoveDataSet" 

Set param = cmd.CreateParameter("@DataSetID", adInteger, adParamInput, , stDataSet) 
cmd.Parameters.Append param 
Set param = cmd.CreateParameter("@Destination", adChar, adParamInput, 1, stDestination) 
cmd.Parameters.Append param 

rs.CursorType = adOpenStatic 
rs.CursorLocation = adUseClient 
rs.LockType = adLockOptimistic 
'rs.Open cmd 
Set rs = cmd.Execute 
If rs!errstatusok = True Then 
    stMessage = "Operation appears to have been successful, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: [" 
Else 
    stMessage = "Operation appears to have failed, check the DataSets Listing..." & Chr(13) & "Also, the Server returned the following information: [" 
End If 
For Each fld In rs.Fields 
    stMessage = stMessage & "| " & fld.Name & "/" & fld.Value & " |" 
Next fld 
stMessage = stMessage & "]" 

MsgBox stMessage 

này trả về folliwing: Operation appears to have failed, check the DataSets Listing... Also, the Server returned the following information: [| errStatusOK/False || countCurrent/0 || countHistorical/10 |]

+0

Bạn chắc chắn có thể sử dụng các tham số đầu ra cũng như giá trị trả lại hoặc các bản ghi bị ảnh hưởng. Xem câu trả lời của tôi. –

4

Một số cách có thể xảy ra để có được giá trị trở lại sử dụng VBA.

  1. Recordset
  2. Tính của hồ sơ bị ảnh hưởng (chỉ dành cho Insert/Update/Delete khác -1)
  3. tham số Output
  4. giá trị Return

Mã của tôi thể hiện tất cả bốn. Đây là thủ tục được lưu trữ trả về một giá trị:

Create PROCEDURE CheckExpedite 
    @InputX varchar(10), 
    @InputY int, 
    @HasExpedite int out 
AS 
BEGIN 
    Select @HasExpedite = 9 from <Table> 
    where Column2 = @InputX and Column3 = @InputY 

    If @HasExpedite = 9 
     Return 2 
    Else 
     Return 3 
End 

Đây là phụ tôi sử dụng trong Excel VBA. Bạn cần tham khảo thư viện Microsoft ActiveX Data Objects 2.8.

Sub CheckValue() 

    Dim InputX As String: InputX = "6000" 
    Dim InputY As Integer: InputY = 2014 

    'open connnection 
    Dim ACon As New Connection 
    'ACon.Open ("Provider=SQLOLEDB;Data Source=<SqlServer>;" & _ 
    ' "Initial Catalog=<Table>;Integrated Security=SSPI") 

    'set command 
    Dim ACmd As New Command 
    Set ACmd.ActiveConnection = ACon 
    ACmd.CommandText = "CheckExpedite" 
    ACmd.CommandType = adCmdStoredProc 

    'Return value must be first parameter else you'll get error from too many parameters 
    'Procedure or function "Name" has too many arguments specified. 
    ACmd.Parameters.Append ACmd.CreateParameter("ReturnValue", adInteger, adParamReturnValue) 
    ACmd.Parameters.Append ACmd.CreateParameter("InputX", adVarChar, adParamInput, 10, InputX) 
    ACmd.Parameters.Append ACmd.CreateParameter("InputY", adInteger, adParamInput, 6, InputY) 
    ACmd.Parameters.Append ACmd.CreateParameter("HasExpedite", adInteger, adParamOutput) 

    Dim RS As Recordset 
    Dim RecordsAffected As Long 

    'execute query that returns value 
    Call ACmd.Execute(RecordsAffected:=RecordsAffected, Options:=adExecuteNoRecords) 

    'execute query that returns recordset 
    'Set RS = ACmd.Execute(RecordsAffected:=RecordsAffected) 

    'get records affected, return value and output parameter 
    Debug.Print "Records affected: " & RecordsAffected 
    Debug.Print "Return value: " & ACmd.Parameters("ReturnValue") 
    Debug.Print "Output param: " & ACmd.Parameters("HasExpedite") 

    'use record set here 
    '... 

    'close 
    If Not RS Is Nothing Then RS.Close 
    ACon.Close 

End Sub