ADO Command 对象
ADO Command 对象中文讲解
在 ADO(ActiveX Data Objects) 中,Command 对象 是一个强大的工具,用于执行数据库命令(如 SQL 查询、插入、更新、删除或调用存储过程)。它特别适合需要安全性和复杂性的场景,例如通过参数化查询防止 SQL 注入。Command 对象在经典 ASP、VBA、VB6 或 Python(通过 pywin32
)等环境中广泛使用,适用于动态输入或需要精确控制的数据库操作。
本教程详细讲解 ADO Command 对象 的用法、属性、方法,并结合上下文(如 REST API、ChromeDriver、Cron、Traefik、列表推导式)提供实用示例。假设你已熟悉 ADO 的 Connection、Recordset、查询 等(参考前文)。
一、ADO Command 对象核心概念
- 作用:
- 执行 SQL 语句(
SELECT
、INSERT
、UPDATE
、DELETE
)。 - 调用数据库存储过程。
- 支持参数化查询,防止 SQL 注入。
- 关键特性:
- 参数化查询:通过
Parameters
集合传递参数,避免直接拼接用户输入。 - 灵活性:支持返回记录集(
SELECT
查询)或执行非查询命令(如INSERT
)。 - 存储过程:可调用数据库预定义的存储过程。
- 适用场景:
- Web 表单处理动态输入(如 ASP 页面查询或更新)。
- 批量操作数据库(Python 脚本)。
- 定时任务执行复杂查询(Cron/任务计划程序)。
二、ADO Command 对象核心属性和方法
- 主要属性:
- ActiveConnection:指定数据库连接(
ADODB.Connection
对象)。 - CommandText:SQL 语句或存储过程名称。
- CommandType:命令类型(如
adCmdText=1
表示 SQL 语句,adCmdStoredProc=4
表示存储过程)。 - Parameters:参数集合,用于参数化查询。
- Prepared:是否预编译 SQL(
True
提高性能)。
- 主要方法:
- Execute:执行命令,返回记录集(
SELECT
)或受影响行数(INSERT
/UPDATE
/DELETE
)。 - CreateParameter:创建参数,添加到
Parameters
集合。 - Parameters.Append:添加参数到命令。
- 常用常量(需引用 ADO 库或手动定义):
- 命令类型:
adCmdText=1
:普通 SQL 语句。adCmdStoredProc=4
:存储过程。
- 参数类型:
adVarChar=200
:字符串。adInteger=3
:整数。adDate=7
:日期。
- 参数方向:
adParamInput=1
:输入参数。adParamOutput=2
:输出参数。
三、Command 对象用法
1. 经典 ASP(VBScript)
使用 Command
执行参数化查询或存储过程。
示例:参数化 SELECT 查询
<%@ Language=VBScript %>
<html>
<head>
<title>ADO Command 查询</title>
</head>
<body>
<h2>客户列表</h2>
<table border="1">
<tr>
<th>公司名称</th>
<th>联系人</th>
</tr>
<%
' 创建连接和命令
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
Do Until rs.EOF
Response.Write "<tr><td>" & Server.HTMLEncode(rs("CompanyName")) & "</td><td>" & Server.HTMLEncode(rs("ContactName")) & "</td></tr>"
rs.MoveNext
Loop
' 清理资源
rs.Close
conn.Close
Set rs = Nothing
Set cmd = Nothing
Set conn = Nothing
%>
</table>
</body>
</html>
- 输出:HTML 表格显示美国客户的列表。
- 关键点:
cmd.Parameters.Append
:添加参数,防止 SQL 注入。cmd.Execute
:返回 Recordset。- 调试(类似 console.log):
Response.Write rs("CompanyName")
。
示例:参数化 INSERT
<%
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 = "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")
cmd.Execute
Response.Write "插入成功!"
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"))
# 执行查询
rs = cmd.Execute()[0] # 返回 Recordset
while not rs.EOF:
print(f"{str(rs.Fields('CompanyName').Value):<30} {str(rs.Fields('ContactName').Value):<20}")
rs.MoveNext()
# 清理资源
rs.Close()
conn.Close()
- 输出:
Around the Horn Thomas Hardy
Great Lakes Food Market Howard Snyder
...
- 调试:
print(repr(rs.Fields))
或print(str(rs.Fields("CompanyName").Value))
.
示例:参数化 UPDATE
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 = "UPDATE Customers SET CompanyName=?, ContactName=? WHERE CustomerID=?"
cmd.CommandType = 1
cmd.Parameters.Append(cmd.CreateParameter("CompanyName", 200, 1, 40, "Updated Corp"))
cmd.Parameters.Append(cmd.CreateParameter("ContactName", 200, 1, 30, "John Updated"))
cmd.Parameters.Append(cmd.CreateParameter("CustomerID", 200, 1, 5, "ALFKI"))
cmd.Execute()
print("更新成功!")
conn.Close()
四、结合上下文的应用
- 结合 REST API:
- ASP:通过表单执行查询,返回 JSON。
<% If Request.Form("submit") <> "" Then 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.ContentType = "application/json" 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"])) 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)
- 结合 ChromeDriver 和 Selenium:
- 测试 ASP 页面(Command 查询生成)。
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()
- 结合 Linux Cron(Windows 任务计划程序):
- 定时执行 Command 查询,输出到 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() print("CSV 导出完成!") conn.Close()
- 保存为
ado_command.py
,通过 Windows 任务计划程序运行。
- 保存为
- 结合 Traefik:
- Traefik 代理 ASP 网站(Command 查询提供数据)。
yaml services: asp: image: my-asp-app labels: - "traefik.http.routers.asp.rule=Host(`asp.example.com`)" - "traefik.http.routers.asp.entrypoints=websecure"
- 结合列表推导式:
- 处理 Command 查询结果。
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()
- 结合
==
和is
:
- 检查 Command 状态:
python if cmd.ActiveConnection is not None: # 身份比较 print("Command connected") if rs.State == 1: # 值比较 print("Recordset open")
- 结合
str()
和repr()
:
- 调试查询结果:
python while not rs.EOF: print(str(rs.Fields("CompanyName").Value)) # 用户友好 print(repr(rs.Fields("CompanyName").Value)) # 调试 rs.MoveNext()
五、注意事项
- 参数化查询:
- 始终使用
Parameters
防止 SQL 注入:asp ' 错误示例 cmd.CommandText = "SELECT * FROM Customers WHERE Country='" & Request("country") & "'"
- 性能:
- 设置
cmd.Prepared = True
预编译 SQL,提高重复执行效率。 - 限制查询范围(如
SELECT TOP 10
)。
- 错误处理:
- 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"Error: {e}")
- 调试(类似 console.log):
- ASP:
Response.Write cmd.CommandText
. - Python:
print(repr(rs.Fields))
.
- 存储过程:
- 示例(调用存储过程):
asp cmd.CommandText = "CustOrderHist" cmd.CommandType = 4 ' adCmdStoredProc cmd.Parameters.Append cmd.CreateParameter("CustomerID", 200, 1, 5, "ALFKI") Set rs = cmd.Execute
- 现代替代:
- Python:
pyodbc
或sqlalchemy
. - .NET:ADO.NET 或 Entity Framework.
六、总结
- ADO Command 对象:通过参数化查询执行 SQL 或存储过程,安全高效。
- 关键步骤:设置连接、定义命令、添加参数、执行命令、处理结果。
- 结合上下文:
- REST API:处理动态查询,返回 JSON。
- ChromeDriver:测试查询页面。
- Cron:定时导出数据。
- Traefik:代理 ASP 服务。
- 列表推导式:处理查询结果。
- 调试:使用
Response.Write
(ASP)或print(repr())
(Python)。
如果需要更复杂的 Command 示例(如存储过程、事务)或特定调试帮助,请提供更多细节!