【问题标题】:How do I associate Parameters to Command objects in ADO with VBScript?如何使用 VBScript 将参数与 ADO 中的命令对象相关联?
【发布时间】:2010-04-01 01:22:08
【问题描述】:

我一直在使用 ADO VBScript,它需要接受参数并将这些参数合并到传递给数据库的查询字符串中。当记录集对象尝试打开时,我不断收到错误消息。如果我传递一个不带参数的查询,记录集就会打开,我可以处理数据。当我通过调试器运行脚本时,命令对象不显示参数对象的值。在我看来,我缺少将 Command 对象和 Parameter 对象相关联的东西,但我不知道是什么。下面是一些 VBScript 代码:

...
'Open Text file to collect SQL query string'
Set fso = CreateObject("Scripting.FileSystemObject")
fileName = "C:\SQLFUN\Limits_ADO.sql"
Set tso = fso.OpenTextFile(fileName, FORREADING)

SQL = tso.ReadAll

'Create ADO instance'
 connString = "DRIVER={SQL Server};SERVER=myserver;UID=MyName;PWD=notapassword;   Database=favoriteDB"
 Set connection = CreateObject("ADODB.Connection")
 Set cmd = CreateObject("ADODB.Command")

  connection.Open connString
  cmd.ActiveConnection = connection
  cmd.CommandText = SQL
  cmd.CommandType = adCmdText

  Set paramTotals = cmd.CreateParameter
  With paramTotals
       .value = "tot%"
       .Name = "Param1"
  End With

  'The error occurs on the next line'
  Set recordset = cmd.Execute

  If recordset.EOF then
      WScript.Echo "No Data Returned"
  Else
      Do Until recordset.EOF
            WScript.Echo recordset.Fields.Item(0) ' & vbTab & recordset.Fields.Item(1)
            recordset.MoveNext
      Loop
  End If

我使用的 SQL 字符串是相当标准的,只是我想向它传递一个参数。是这样的:

SELECT column1
FROM table1
WHERE column1 IS LIKE ?

我知道 ADO 应该替换“?”使用我在脚本中分配的参数值。我看到的问题是 Parameter 对象显示正确的值,但根据我的调试器,命令对象的参数字段为 null。

【问题讨论】:

    标签: vbscript ado


    【解决方案1】:

    我知道这已经过时了,但对于仍然相信这个的任何人(就像我通过谷歌所做的那样):

    如果您使用的是存储过程:

    set cmd = Server.CreateObject("ADODB.Command")
    with cmd
        .ActiveConnection = db_connection
        .CommandText = "stored_procedure_name"
        .CommandType = adCmdStoredProc
        .Parameters.Append .CreateParameter("@Parameter1",adInteger,adParamInput,,1)
            .Parameters.Append .CreateParameter("@Parameter2",adVarChar,adParamInput,100,"Up to 100 chars")
            .Parameters.Append .CreateParameter("@Parameter3",adBoolean,adParamInput,,true)
            .Parameters.Append .CreateParameter("@Parameter4",adDBTimeStamp,adParamInput,,now())
    end with
    set rs = cmd.execute
        'do stuff with returned results from select or leave blank if insert/delete/etc stored procedure
    set rs = nothing
    set cmd = nothing
    

    如果不是,我相信您将 .CommandText 更改为带有问号的 SQL 语句,并且您的参数必须遵循相同的顺序。

    见http://www.devguru.com/technologies/ado/quickref/command_createparameter.html 有关您使用 CreateParameter 传递的值的细分,以及类型及其描述的列表。

    【讨论】:

      【解决方案2】:

      创建参数后,必须在执行命令之前将其附加到命令对象的参数集合中:

      Set paramTotals = cmd.CreateParameter
      With paramTotals
          .Value = "tot%"
          .Name = "Param1"
      End With
      
      cmd.Parameters.Append paramTotals
      

      您可能还需要为参数指定Type 和Size 属性。通常,我使用 CreateParameter 函数的参数在一行中设置所有必要的属性:

      Set paramTotals = cmd.CreateParameter("Param1", adVarChar, adParamInput, 30, "tot%")
      cmd.Parameters.Append paramTotals
      

      【讨论】:

        【解决方案3】:

        我从来没有让CreateParameter 做我想做的事。正确的参数化是避免 SQL 注入的必要条件,但CreateParameter 是一个完整的 PITA。值得庆幸的是,还有一个替代方案:Command.Execute 直接接受参数。

        dim cmd, rs, rows_affected
        set cmd = Server.createObject("adodb.command")
        cmd.commandText = "select from Foo where id=?"
        set cmd.activeConnection = someConnection
        set rs = cmd.execute(rows_affected, Array(42))
        

        包裹在适当的抽象中会更好。我编写了自己的数据库类包装ADODB.Connection,所以我不必手动完成所有这些工作。它有点依赖于其他自定义类,但它的要点应该很明显:

        class DatabaseClass
        '   A database abstraction class with a more convenient interface than
        '   ADODB.Connection. Provides several simple methods to safely query a
        '   database without the risk of SQL injection or the half-dozen lines of
        '   boilerplate otherwise necessary to avoid it.
        '   
        '   Example:
        '   
        '   dim db, record, record_set, rows_affected
        '   set db = Database("/path/to/db")
        '   set record = db.get_record("select * from T where id=?;", Array(42))
        '   set record_set = db.get_records("select * from T;", empty)
        '   rows_affected = db.execute("delete from T where foo=? and bar=?",
        '                              Array("foo; select from T where bar=", true))
        
            private connection_
        '       An ADODB connection object. Should never be null.
        
            private sub CLASS_TERMINATE
                connection_.close
            end sub
        
            public function init (path)
        '       Initializes a new database with an ADODB connection to the database at
        '       the specified path. Path must be a relative server path to an Access
        '       database. Returns me.
        
                set connection_ = Server.createObject ("adodb.connection")
                connection_.provider = "Microsoft.Jet.OLEDB.4.0"
                connection_.open Server.mapPath(path)
        
                set init = me
            end function
        
            public function get_record (query, args)
        '       Fetches the first record returned from the supplied query wrapped in a
        '       HeavyRecord, or nothing if there are no results. 
        
                dim data: set data = native_recordset(query, args)
                if data.eof then
                    set get_record = nothing
                else
                    set get_record = (new HeavyRecordClass).init(data)
                end if
            end function
        
            public function get_records (query, args)
        '       Fetches all records returned from the supplied query wrapped in a
        '       RecordSet (different from the ADODB recordset; implemented below).
        
                set get_records = (new RecordSetClass).init(native_recordset(query, args))
            end function
        
            public function execute (query, args)
        '       Executes the supplied query and returns the number of rows affected.
        
                dim rows_affected
                build_command(query).execute rows_affected, args
                execute = rows_affected
            end function
        
            private function build_command (query)
        '       Helper method to build an ADODB command from the supplied query.
        
                set build_command = Server.createObject("adodb.command")
                build_command.commandText = query
                set build_command.activeConnection = connection_
            end function
        
            private function native_recordset (query, args)
        '       Helper method that takes a query string and array of arguments, queries
        '       the ADODB connection, and returns an ADODB recordset containing the
        '       result.
        
                set native_recordset = build_command(query).execute( , args) ' Omits out-parameter for number of rows
            end function
        end class
        

        【讨论】:

        • 这对我有用 --- 谢谢!读者请注意:.Execute 的 Parameters 参数采用 Variant。如果参数的数量和格式与查询的预期不匹配,您将收到非常模糊的错误消息!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多