2010-04-01 44 views
5

Parametreleri kabul etmesi ve bu parametreleri veritabanını geçiren Sorgu dizesinde içermesi gereken bir ADO VBScript çalışıyorum. Kayıt Kümesi Nesnesi açmaya çalışırken hata almaya devam ediyorum. Bir sorguyu parametreler olmadan iletirsem, kayıt kümesi açılır ve verilerle çalışabilirim. Komut dosyası bir hata ayıklayıcısından çalıştırdığımda, komut nesnesi parametre nesnesi için bir değer göstermez. Bana öyle geliyor ki, Command nesnesini ve Parametre nesnesini ilişkilendiren bir şeyi özlüyorum ama ne olduğunu bilmiyorum. Ben bunun için parametre geçirmek isteyen haricinde oldukça standarttır kullanmakParametreleri, ADS'deki VBScript ile Komut nesnelerine nasıl ilişkilendiririm?

... 
'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 dizesi: İşte VBScript Kanununun biraz. Böyle bir şeydir: "?" Diye ADO değiştirmeniz gerekir anlamak

SELECT column1 
FROM table1 
WHERE column1 IS LIKE ? 

komut dosyasında I parametre parametresi ile atayın. Gördüğüm sorun, Parametre nesnesinin doğru değeri göstermesidir, ancak hata ayıklayıcım uyarınca komut nesnesinin parametre alanı boştur.

cevap

2

Ne istediğimi yapamadım CreateParameter. Uygun bir parametrelendirme, SQL enjeksiyonunu önlemek için bir zorunluluktur, ancak CreateParameter tam bir PITA'dır. Neyse ki, bir alternatif var: Command.Execute doğrudan parametreleri alır.

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

Uygun bir soyutlamaya sarıldığında çok daha güzel. Kendi veritabanı sınıfımı ADODB.Connection sarmalayarak yazdım, böylece tüm bunları el ile yapmak zorunda kalmayacağım. Diğer özel sınıflar üzerinde biraz güvenir, ama özü belirgin olmalıdır:

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

Bu benim için çalıştı --- teşekkürler! Okuyucular lütfen dikkat ediniz: '.Execute'' 'Parameters' argümanı' Variant'ı alır. Parametrelerinizin sayısı ve biçimleri, sorgunun beklediği eşleşme ile uyuşmuyorsa çok belirsiz hata iletileri alacaksınız! – cxw

0

Eğer parametreyi oluşturduktan sonra, sen Command yürütmek önce Komut nesnesinin Parameters koleksiyonuna ekler zorunda:

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

cmd.Parameters.Append paramTotals 

Ayrıca Parametre için Type ve Size özelliklerini belirtmeniz gerekebilir. Genellikle, bir satırda gerekli tüm özellikleri ayarlamak için CreateParameter işlevinin bağımsız değişkenleri kullanın: Bu eski, ama yine de bu fiding herkes için biliyorum

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

(google aracılığıyla yaptığı gibi):

Eğer Saklanan kullanarak ediyorsanız Prosedürleri:

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 

Eğer değilse, yerinde soru işaretlerinin ile SQL açıklamaya .CommandText değiştirmek ve Parametreler aynı sırasını takip etmek zorundadır inanıyoruz.

Bkz. http://www.devguru.com/technologies/ado/quickref/command_createparameter.html CreateParameter ile geçirdiğiniz değerlerin yanı sıra türlerin ve açıklamaların bir listesi için.