Pertanyaan Bagaimana cara mengaitkan Parameter ke objek Command di ADO dengan VBScript?


Saya telah bekerja ADO VBScript yang perlu menerima parameter dan menggabungkan parameter-parameter dalam string Query yang lolos database. Saya terus mendapatkan kesalahan ketika Record Set Object mencoba untuk membuka. Jika saya mengirimkan query tanpa parameter, recordset terbuka dan saya bisa bekerja dengan data. Ketika saya menjalankan skrip melalui debugger, objek perintah tidak menunjukkan nilai untuk objek parameter. Sepertinya saya kehilangan sesuatu yang mengaitkan objek Command dan objek Parameter, tetapi saya tidak tahu apa. Berikut ini sedikit Kode 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

String SQL yang saya gunakan cukup standar kecuali saya ingin melewatkan parameter untuk itu. Ini adalah sesuatu seperti ini:

SELECT column1
FROM table1
WHERE column1 IS LIKE ?

Saya mengerti bahwa ADO harus mengganti "?" dengan nilai parameter yang saya tetapkan dalam skrip. Masalah yang saya lihat adalah bahwa objek Parameter menunjukkan nilai yang benar, tetapi bidang parameter objek perintah adalah nol menurut debugger saya.


5
2018-04-01 01:22


asal


Jawaban:


Saya tahu ini sudah tua, tetapi bagi siapa pun yang masih memahaminya (seperti yang saya lakukan melalui google):

Jika Anda menggunakan Stored Procedures:

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

Jika tidak, saya percaya Anda mengubah .CommandText ke pernyataan SQL Anda dengan tanda tanya di tempat dan Parameter Anda harus mengikuti urutan yang sama.

Lihat http://www.devguru.com/technologies/ado/quickref/command_createparameter.html Untuk rincian nilai-nilai apa yang Anda lalui dengan CreateParameter, serta daftar jenis dan uraiannya.


5
2017-11-03 20:15



Saya tidak pernah mendapatkannya CreateParameter melakukan apa yang saya inginkan. Parameterisasi yang tepat adalah suatu keharusan untuk menghindari injeksi SQL, tetapi CreateParameter adalah PITA lengkap. Untungnya, ada alternatif: Command.Execute mengambil parameter secara langsung.

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))

Jauh lebih bagus jika dibungkus dengan abstraksi yang tepat. Saya menulis pembungkus kelas database saya sendiri ADODB.Connection jadi saya tidak perlu melakukan semua ini secara manual. Ini bergantung sedikit pada kelas khusus lainnya, tetapi intinya harus jelas:

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

2
2018-05-28 17:58



Setelah Anda membuat parameter, Anda harus menambahkannya ke koleksi parameter objek perintah sebelum Anda menjalankan perintah:

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

cmd.Parameters.Append paramTotals

Anda mungkin juga perlu menentukan Type dan Size properti untuk Parameter. Secara umum, saya menggunakan argumen fungsi CreateParameter untuk mengatur semua properti yang diperlukan dalam satu baris:

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

1
2017-09-17 06:23