8

Ho impostato una stored procedure in SQL Server che funziona correttamente. Ora posso chiamare da VBA, ma si vuole restituire un valore di sapere se si sono verificati errori, ecc L'ultimo parametro nel mio SP è impostato come USCITA:Come restituire i valori da una stored procedure di SQL Server e utilizzarli in Access VBA

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

mio VBA per chiamare il SP è al di sotto , ma non funzionerà ora, dopo aver aggiunto il nuovo parametro e non sono sicuro dove sto andando male, continuo a ricevere 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 

Come posso ottenere il VBA per lavorare con l'uscita parametro e rendere il valore restituito 'leggibile' dal vba.

MODIFICA - Ho modificato la domanda in modo più specifico sulla restituzione dei valori e non sull'utilizzo dei parametri OUTPUT.

risposta

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

È necessario aver postato questo mentre stavo pubblicando la mia risposta, capisco come ho sbagliato con il CreateParameter ora. Molte grazie, potrebbe usarlo in futuro. – aSystemOverload

2

Tra le altre enumerazioni di parametri da cui viene prelevato "adParamInput", un altro è "adParamOutput", che indica un parametro out da una stored procedure e "adParamInputOutput" per un parametro che va "both directions", come fosse. Nel tuo caso, credo che "adParamOutput" sarebbe appropriato. Spero che questo sia quello che stai cercando.

+0

Non quello che stavo cercando, ma utile. Un collega mi ha suggerito di fornire l'output tramite un SELECT @errStatusOK ecc. E di manipolarlo nel VBA, che ha funzionato bene. Grazie – aSystemOverload

4

avevo inizialmente guardato parametri di output, ma non riuscivo a trovare il modo per farli tornare ad Access (in VBA) per poi fornire un feedback all'utente. Un collega ha suggerito di utilizzare un SELEZIONA nella procedura memorizzata e di usarlo.

stored procedure: aggiunto il seguente alla fine:

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 

Ciò restituisce il folliwing: Operation appears to have failed, check the DataSets Listing... Also, the Server returned the following information: [| errStatusOK/False || countCurrent/0 || countHistorical/10 |]

+0

È possibile utilizzare i parametri di output, nonché il valore restituito o i record interessati. Vedi la mia risposta. –

4

Diversi modi sono possibili per ottenere i valori indietro usando VBA.

  1. Recordset
  2. conte di record interessati (solo per Insert/Update/Delete altrimenti -1)
  3. parametro di uscita
  4. valore di ritorno

Il mio codice dimostra tutti e quattro. Ecco una stored procedure che restituisce un valore:

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 

Ecco il sub che uso in Excel VBA. È necessario fare riferimento alla libreria 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