【问题标题】:How to call a stored procedure in an if statement using pass through query?如何使用传递查询在 if 语句中调用存储过程?
【发布时间】:2017-07-11 14:18:27
【问题描述】:

我正在为我的应用程序使用 MS Access VBA 和 SQL Server 存储过程。我有一个表单 frmUsers,它有一个文本框 UserName。它绑定到 tblUsers 的用户名。如果用户在文本框输入值前使用“@”更新它,则必须清除 SQL 表tblUser 中的某些列(PasswordHash)。

我已经为它创建了一个存储过程,并且还在 UserName_AfterUpdate 下编写了一些代码。我觉得我需要创建一个传递查询来调用If 语句中的存储过程,如下所示;但它不起作用(没有删除表中的值,也没有给出任何错误)。

存储过程本身可以工作,但是当我尝试使用应用程序测试它时,即在文本框前面插入“@”,它不会删除表中的两列。我错过了在传递查询和文本框之间绑定的东西。请帮忙。

MS Access VBA

Private Sub UserName_AfterUpdate()
    On Error Resume Next
    Dim frm As Form
    Dim strFilter As String

    Dim DB As Database
    Set DB = CodeDb

    DoCmd.OpenForm "frmUsers", , , , , acDialog
    Set frm = Forms!frmUsers

    If frm.Tag Then
        strFilter = strFilter & "sp_ClearWebsitePwd"
        strFilter = strFilter & ", " & frm!UserID      

        If Left(UserName, 1) = "@" Then        

            DB.QueryDefs("qryClearWebsitePwd").Connect = SQLConnectString
            DB.QueryDefs("qryClearWebsitePwd").sql = strFilter
        End If  
    End If
End Sub

SQL Server存储过程

CREATE PROCEDURE [dbo].[sp_ClearWebsitePwd] 
    @userID INT
AS
BEGIN
    SET NOCOUNT ON; 

    UPDATE tblUser
    SET tblUser.Password = NULL, tblUser.Hash = NULL
    WHERE UserID = @userID 
END         

MS Access 直通查询(qryClearWebsitePwd)

sp_ClearWebsitePwd, 20226

【问题讨论】:

  • 我想Password 字段是加密的?考虑到您(显然)存储了Hash,为什么您甚至需要它?
  • @Mat'sMug:我只是为表格列命名。我需要取消两列。保持'@'在前面意味着从系统/应用程序中停用用户。
  • 抱歉,为什么不明确delete功能来删除记录?
  • 您的过程被命名为UserName_AfterUpdate(),表示它附加到表单上某个名为UserName 的文本框。在您的代码中,您正在查看一个名为CustomerName 的变量,以查看第一个字符是否为@。如果您将Option Explicit 作为代码模块的第一行并尝试编译,我愿意这样做,VBE 会告诉您CustomerName 是一个未声明的变量。 ...
  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!

标签: sql vba ms-access stored-procedures pass-through


【解决方案1】:

从根本上说,您不会.Execute 您的查询,所以它什么也不做。您只需更改其 SQL 和连接字符串属性。

另外,调用存储过程时不需要逗号分隔或“@”前缀。从表单中删除“@”用户指令并传递整数。如果连接属性永远不会改变,则不需要更新它,因此可以删除该行。

If frm.Tag Then
    strFilter = "sp_ClearWebsitePwd " & frm!UserID      

    DB.QueryDefs("qryClearWebsitePwd").Connect = SQLConnectString
    DB.QueryDefs("qryClearWebsitePwd").SQL = strFilter
    DB.QueryDefs("qryClearWebsitePwd").Execute dbFailOnError
End If

【讨论】:

    【解决方案2】:

    因为“@”不是整数,但你的参数是

    CREATE PROCEDURE [dbo].[sp_ClearWebsitePwd] 
      @userID INT
    AS
    

    为了更清楚:

    • 用户在frm.UserID中输入@123
    • 代码连接strFilter & [sp 名称] & @123
    • IF 语句查看 frm.UserID 的第一个字符,确定它是 @,然后继续进入代码的 True 部分
    • true 部分将@123 作为参数传递给存储过程
    • 存储过程需要一个整数,所以当它得到一个字符串时它会安静地吐字,不返回任何错误指示

    修复它:

    If frm.Tag Then
        If Left(CustomerName, 1) = "@" Then        
            strFilter = strFilter & "sp_ClearWebsitePwd" 
            strFilter = strFilter & ", " & right(frm!UserID, len(frm!UserID) - 1)
    
            DB.QueryDefs("qryClearWebsitePwd").Connect = SQLConnectString
            DB.QueryDefs("qryClearWebsitePwd").sql = strFilter
        End If  
    End If
    'assumes something happens here to actually execute the query
    

    这将在将 UserID 中的前导 @ 修剪为 作为 int 传递它之前。

    老实说,我建议您尝试找到另一个触发值来指示帐户已被禁用。也许考虑添加一个“活动”字段(将所有人设置为 True)并使用您的 SP 将其设置为 False,或者相反,添加一个“禁用”字段(将所有人设置为 False)并使用您的 SP 将该字段设置为“真的'。

    【讨论】:

    • 似乎 OP 正在将 UserId 值连接到 SP 调用 (strFilter & ", " & frm!UserID) 中,并且 @CustomerName 字段的一部分。
    • 是的,但是frm!UserID 包含@123,这就是为什么初始字符@ 可以用作进入执行SP 的IF 的触发器。 @,是字符串的一部分,它被传递到需要整数参数的 SP 中。 @123 不是整数。
    • 好的,终于看到@Mat'sMug 在说什么了——这是漫长的一天。在 OP 更明确之前,这可能无法解决任何问题。
    【解决方案3】:

    感谢大家帮助我。我发现我错过了什么。一切都是正确的,除了我错过了设置DB.QueryDefs("qryClearWebsitePwd").ReturnsRecords = False 所以,正确的版本是:

    Private Sub UserName_AfterUpdate()
        On Error Resume Next
        Dim frm As Form
        Dim strFilter As String
    
        Dim DB As Database
        Set DB = CodeDb
    
        DoCmd.OpenForm "frmUsers", , , , , acDialog
        Set frm = Forms!frmUsers
    
        If frm.Tag Then
            strFilter = strFilter & "sp_ClearWebsitePwd"
            strFilter = strFilter & ", " & frm!UserID      
    
            If Left(UserName, 1) = "@" Then        
    
                DB.QueryDefs("qryClearWebsitePwd").Connect = SQLConnectString
                DB.QueryDefs("qryClearWebsitePwd").ReturnsRecords = False
                DB.QueryDefs("qryClearWebsitePwd").sql = strFilter
                DB.QueryDefs("qryClearWebsitePwd").Execute dbFailOnError
            End If  
        End If
    End Sub
    

    一旦我添加了这行代码,它就可以正常工作了。似乎 SQL 正在等待一些返回值,但访问没有返回任何内容。

    【讨论】:

      猜你喜欢
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      相关资源
      最近更新 更多