2010-04-01 1 views
5

Я работаю с ADO VBScript, который должен принимать параметры и включать эти параметры в строку Query, которая передается базе данных. Я продолжаю получать ошибки, когда объект набора записей пытается открыть. Если я передаю запрос без параметров, откроется набор записей, и я смогу работать с данными. Когда я запускаю скрипт через отладчик, объект команды не показывает значение для объекта параметра. Мне кажется, что мне не хватает чего-то, что связывает объект Command и объект Parameter, но я не знаю, что. Вот несколько из VBScript Код:Как связать параметры для объектов Command в ADO с помощью 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 в соответствии с моим отладчиком.

ответ

2

Я никогда не получал 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 
+0

Это сработало для меня --- спасибо! Читатели, пожалуйста, обратите внимание: аргумент 'Parameters' для' .Execute' принимает 'Variant'. Вы получите очень неясные сообщения об ошибках, если число и форматы ваших параметров не соответствуют ожидаемому запросу! – cxw

0

После создания параметра, вы должны добавить его к коллекции параметров объекта Command, прежде чем выполнить команду:

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 
6

Я знаю, что это старый, но для тех, кто еще fiding это (как я сделал с помощью Google):

Если вы используете хранимые процедуры:

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, а также список типов и их описания.