ADO Parameter 对象

ADO Parameter 对象中文讲解

ADO(ActiveX Data Objects) 中,Parameter 对象 是与 Command 对象 配合使用的核心组件,用于定义和传递参数化查询或存储过程的参数。Parameter 对象通过 Parameters 集合 管理,能够有效防止 SQL 注入,提高查询安全性和可维护性。它在经典 ASP、VBA、VB6 或 Python(通过 pywin32)等环境中广泛用于动态 SQL 查询或存储过程调用。

本教程详细讲解 ADO Parameter 对象 的用法、属性、方法,并结合上下文(如 REST API、ChromeDriver、Cron、Traefik、列表推导式)提供实用示例。假设你已熟悉 ADO 的 ConnectionRecordsetCommandErrorField 对象(参考前文)。


一、ADO Parameter 对象核心概念

  • 作用
  • 定义 SQL 查询或存储过程的参数(如 WHERE 子句的值)。
  • 提供类型安全的参数传递,防止 SQL 注入。
  • 支持输入、输出和输入/输出参数(尤其在存储过程中)。
  • Parameters 集合
  • 属于 Command 对象,包含所有 Parameter 对象。
  • 通过 CreateParameter 方法创建并添加到集合。
  • 适用场景
  • Web 表单动态查询(如 ASP 页面搜索用户)。
  • 调用存储过程返回结果。
  • 批量参数化操作(Python 脚本)。
  • 关键点
  • 参数化查询使用占位符(如 ? 或命名参数)。
  • 必须指定参数的类型、方向和大小。

二、Parameter 对象核心属性和方法

  1. 主要属性
  • Name:参数名称(用于命名参数或调试)。
  • Type:参数的数据类型(如 adVarChar=200adInteger=3)。
  • Direction:参数方向(如 adParamInput=1adParamOutput=2)。
  • Size:参数的最大长度(对于字符串或二进制类型)。
  • Value:参数的实际值(可读写)。
  • PrecisionNumericScale:用于数字类型(精度和小数位数)。
  1. 主要方法
  • CreateParameter(Name, Type, Direction, Size, Value):创建 Parameter 对象。
  • Parameters.Append:将 Parameter 添加到 Command 的 Parameters 集合。
  • Parameters.Delete:从集合中删除参数(少用)。
  1. 常用常量(需引用 ADO 库或手动定义):
  • 数据类型:
    • adVarChar=200:字符串。
    • adInteger=3:整数。
    • adDate=7:日期。
    • adDouble=5:双精度浮点数。
  • 方向:
    • adParamInput=1:输入参数。
    • adParamOutput=2:输出参数。
    • adParamInputOutput=3:输入/输出参数。
    • adParamReturnValue=4:存储过程返回值。

三、Parameter 对象用法

1. 经典 ASP(VBScript)

使用 Parameter 对象执行参数化查询或存储过程。

示例:参数化 SELECT 查询

<%@ Language=VBScript %>
<html>
<head>
    <title>ADO Parameter 示例</title>
</head>
<body>
    <h2>客户列表</h2>
    <table border="1">
        <tr>
            <th>公司名称</th>
            <th>联系人</th>
        </tr>
<%
    On Error Resume Next
    Set conn = Server.CreateObject("ADODB.Connection")
    conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb"

    Set cmd = Server.CreateObject("ADODB.Command")
    cmd.ActiveConnection = conn
    cmd.CommandText = "SELECT CompanyName, ContactName FROM Customers WHERE Country=?"
    cmd.CommandType = 1  ' adCmdText
    cmd.Parameters.Append cmd.CreateParameter("Country", 200, 1, 50, "USA")  ' adVarChar, adParamInput

    Set rs = cmd.Execute
    If conn.Errors.Count = 0 Then
        Do Until rs.EOF
            Response.Write "<tr><td>" & Server.HTMLEncode(rs("CompanyName")) & "</td><td>" & Server.HTMLEncode(rs("ContactName")) & "</td></tr>"
            rs.MoveNext
        Loop
    Else
        For Each err In conn.Errors
            Response.Write "错误:" & Server.HTMLEncode(err.Description) & "<br>"
        Next
    End If

    rs.Close
    conn.Close
    Set rs = Nothing
    Set cmd = Nothing
    Set conn = Nothing
%>
    </table>
</body>
</html>
  • 输出:HTML 表格显示美国客户的 CompanyNameContactName
  • 关键点
  • cmd.CreateParameter("Country", 200, 1, 50, "USA"):创建参数。
  • cmd.Parameters.Append:添加到 Parameters 集合。
  • 调试(类似 console.log)Response.Write cmd.Parameters(0).Value.

示例:调用存储过程
假设数据库有存储过程 CustOrderHist(输入参数 CustomerID,返回订单历史)。

<%
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb"

Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "CustOrderHist"
cmd.CommandType = 4  ' adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("CustomerID", 200, 1, 5, "ALFKI")

Set rs = cmd.Execute
Do Until rs.EOF
    Response.Write rs("ProductName") & " - " & rs("Total") & "<br>"
    rs.MoveNext
Loop

rs.Close
conn.Close
Set cmd = Nothing
Set conn = Nothing
%>

2. Python(通过 pywin32)

安装 pywin32

pip install pywin32 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

示例:参数化 SELECT 查询

import win32com.client

# 创建连接和命令
conn = win32com.client.Dispatch("ADODB.Connection")
conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb")

cmd = win32com.client.Dispatch("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "SELECT CompanyName, ContactName FROM Customers WHERE Country=?"
cmd.CommandType = 1  # adCmdText
cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 50, "USA"))

try:
    rs = cmd.Execute()[0]
    print(f"{'CompanyName':<30} {'ContactName':<20}")
    print("-" * 50)
    while not rs.EOF:
        print(f"{str(rs.Fields('CompanyName').Value):<30} {str(rs.Fields('ContactName').Value):<20}")
        rs.MoveNext()
except Exception as e:
    print(f"错误:{e}")
    for err in conn.Errors:
        print(f"错误描述:{err.Description}")

rs.Close()
conn.Close()
  • 输出
  CompanyName                    ContactName
  --------------------------------------------------
  Around the Horn               Thomas Hardy
  Great Lakes Food Market       Howard Snyder
  ...
  • 调试print(repr(cmd.Parameters[0].Value)).

示例:参数化 INSERT

import win32com.client

conn = win32com.client.Dispatch("ADODB.Connection")
conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb")

cmd = win32com.client.Dispatch("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "INSERT INTO Customers (CustomerID, CompanyName, ContactName, Country) VALUES (?, ?, ?, ?)"
cmd.CommandType = 1
cmd.Parameters.Append(cmd.CreateParameter("CustomerID", 200, 1, 5, "XYZ01"))
cmd.Parameters.Append(cmd.CreateParameter("CompanyName", 200, 1, 40, "XYZ Corp"))
cmd.Parameters.Append(cmd.CreateParameter("ContactName", 200, 1, 30, "John Doe"))
cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 15, "USA"))

try:
    cmd.Execute()
    print("插入成功!")
except Exception as e:
    print(f"错误:{e}")

conn.Close()

四、结合上下文的应用

  1. 结合 REST API
  • ASP:通过表单动态查询,返回 JSON。 <% If Request.Form("submit") <> "" Then Response.ContentType = "application/json" Set conn = Server.CreateObject("ADODB.Connection") conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb" Set cmd = Server.CreateObject("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT CompanyName, ContactName FROM Customers WHERE Country=?" cmd.CommandType = 1 cmd.Parameters.Append cmd.CreateParameter("Country", 200, 1, 50, Request.Form("country")) Set rs = cmd.Execute Response.Write "[" first = True Do Until rs.EOF If Not first Then Response.Write "," Response.Write "{""company"":""" & Server.HTMLEncode(rs("CompanyName")) & """,""contact"":""" & Server.HTMLEncode(rs("ContactName")) & """}" first = False rs.MoveNext Loop Response.Write "]" rs.Close conn.Close End If %> <form method="post"> Country: <input name="country"><br> <input type="submit" name="submit" value="Query"> </form>
  • Python(Flask)from flask import Flask, request, jsonify import win32com.client app = Flask(__name__) @app.route('/customers', methods=['POST']) def query_customers(): conn = win32com.client.Dispatch("ADODB.Connection") conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb") cmd = win32com.client.Dispatch("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT CompanyName, ContactName FROM Customers WHERE Country=?" cmd.CommandType = 1 cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 50, request.json["country"])) try: rs = cmd.Execute()[0] customers = [{"company": str(rs.Fields("CompanyName").Value), "contact": str(rs.Fields("ContactName").Value)} for _ in range(rs.RecordCount) if not rs.EOF and (rs.MoveNext() or True)] conn.Close() return jsonify(customers) except Exception as e: conn.Close() return jsonify({"error": str(e)}), 500
  1. 结合 ChromeDriver 和 Selenium
  • 测试 ASP 页面(Parameter 查询)。
    python from selenium.webdriver import Chrome from selenium.webdriver.common.by import By driver = Chrome() driver.get('http://localhost/query.asp') driver.find_element(By.NAME, 'country').send_keys('USA') driver.find_element(By.NAME, 'submit').click() print(driver.find_element(By.TAG_NAME, 'table').text) driver.quit()
  1. 结合 Linux Cron(Windows 任务计划程序)
  • 定时执行参数化查询,输出到 CSV。 python import win32com.client from tqdm import tqdm conn = win32com.client.Dispatch("ADODB.Connection") conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb") cmd = win32com.client.Dispatch("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT CompanyName, ContactName FROM Customers WHERE Country=?" cmd.CommandType = 1 cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 50, "USA")) rs = cmd.Execute()[0] with open("customers.csv", "w", encoding="utf-8") as f: f.write("CompanyName,ContactName\n") for _ in tqdm(range(rs.RecordCount), desc="Writing"): if not rs.EOF: f.write(f"{str(rs.Fields('CompanyName').Value)},{str(rs.Fields('ContactName').Value)}\n") rs.MoveNext() conn.Close()
    • 保存为 ado_parameter.py,通过 Windows 任务计划程序运行。
  1. 结合 Traefik
  • Traefik 代理 ASP 网站(Parameter 查询提供数据)。
    yaml services: asp: image: my-asp-app labels: - "traefik.http.routers.asp.rule=Host(`asp.example.com`)" - "traefik.http.routers.asp.entrypoints=websecure"
  1. 结合列表推导式
  • 处理 Parameter 查询结果。
    python import win32com.client conn = win32com.client.Dispatch("ADODB.Connection") conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb") cmd = win32com.client.Dispatch("ADODB.Command") cmd.ActiveConnection = conn cmd.CommandText = "SELECT CompanyName FROM Customers WHERE Country=?" cmd.CommandType = 1 cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 50, "USA")) rs = cmd.Execute()[0] names = [str(rs.Fields("CompanyName").Value) for _ in range(rs.RecordCount) if not rs.EOF and (rs.MoveNext() or True)] print(f"Names: {repr(names)}") conn.Close()
  1. 结合 ==is
  • 检查参数值:
    python if cmd.Parameters(0).Value == "USA": # 值比较 print("Parameter is USA") if cmd.Parameters(0).Value is not None: # 身份比较 print("Parameter has value")
  1. 结合 str()repr()
  • 调试参数值:
    python print(str(cmd.Parameters(0).Value)) # 用户友好 print(repr(cmd.Parameters(0).Value)) # 调试

五、注意事项

  1. 参数顺序
  • 参数顺序必须与 SQL 语句中的 ? 占位符匹配。
  • 命名参数(如 @Country)在某些数据库(如 SQL Server)中支持,但 Access 使用 ?
  1. 数据类型
  • 确保 TypeSize 与数据库字段匹配(如 adVarChar 需要指定长度)。
  • 处理空值(None 或空字符串)以避免错误。
  1. 错误处理
  • ASP:
    asp On Error Resume Next Set rs = cmd.Execute If Err.Number <> 0 Then Response.Write "错误:" & Err.Description
  • Python:
    python try: rs = cmd.Execute()[0] except Exception as e: print(f"错误:{e}")
  1. 性能
  • 设置 cmd.Prepared = True 预编译 SQL,提高重复执行效率。
  • 避免过多参数导致复杂性增加。
  1. 调试(类似 console.log)
  • ASP:Response.Write cmd.Parameters(0).Value.
  • Python:print(repr(cmd.Parameters[0].Value)).
  1. 现代替代
  • Python:pyodbcsqlalchemy(更现代的参数化查询)。
  • .NET:ADO.NET 或 Entity Framework。

六、总结

  • ADO Parameter 对象:通过 Parameters 集合实现参数化查询,安全高效。
  • 关键步骤:创建 Parameter、设置类型和值、添加到 Command、执行命令。
  • 结合上下文
  • REST API:处理动态查询,返回 JSON。
  • ChromeDriver:测试查询页面。
  • Cron:定时导出数据。
  • Traefik:代理 ASP 服务。
  • 列表推导式:处理查询结果。
  • 调试:使用 Response.Write(ASP)或 print(repr())(Python)。

如果需要更复杂的 Parameter 示例(如存储过程输出参数、批量参数化)或特定调试帮助,请提供更多细节!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注