ADO 查询
ADO 查询(Query)简介
在 ADO(ActiveX Data Objects) 中,查询是通过 Recordset 或 Command 对象执行 SQL 语句,从数据库中检索数据或执行操作(如插入、更新、删除)。ADO 查询是数据库交互的核心功能,支持 SQL 语言,适用于经典 ASP、VBA、VB6 和 Python(通过 pywin32
)等环境。查询结果通常存储在 Recordset 中,用于后续显示或处理。
本教程聚焦 ADO 查询的实现,涵盖 SQL 查询、参数化查询、执行方式,并结合上下文(如 REST API、ChromeDriver、Cron、Traefik、列表推导式)提供实用示例。假设你已熟悉 ADO 的 Connection 和 Recordset(参考前文)。
一、ADO 查询核心概念
- 查询类型:
- SELECT:检索数据,返回 Recordset。
- INSERT/UPDATE/DELETE:修改数据,返回受影响行数(通过
Command
或Connection.Execute
)。 - 存储过程:调用数据库预定义过程。
- 执行方式:
- Recordset.Open:直接打开记录集,适合 SELECT 查询。
- Connection.Execute:执行 SQL,返回记录集或受影响行数。
- Command.Execute:支持参数化查询,防止 SQL 注入。
- 关键对象:
- Connection:提供数据库连接。
- Recordset:存储查询结果。
- Command:执行带参数的 SQL 语句。
二、ADO 查询方式
1. 使用 Recordset.Open
直接通过 Recordset 执行 SELECT 查询,适合简单场景。
ASP 示例(查询客户):
<%
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb"
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open "SELECT CompanyName, ContactName FROM Customers WHERE Country='USA'", conn, 3, 1 ' adOpenStatic, adLockReadOnly
Do Until rs.EOF
Response.Write Server.HTMLEncode(rs("CompanyName")) & "<br>"
rs.MoveNext
Loop
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
%>
- 关键点:
rs.Open sql, conn, cursorType, lockType
:cursorType=3
(adOpenStatic),lockType=1
(adLockReadOnly)适合只读查询。Server.HTMLEncode
:防止 XSS 攻击。- 调试(类似 console.log):
Response.Write rs.Fields("CompanyName").Value
.
2. 使用 Connection.Execute
通过 Connection 对象直接执行 SQL,适合简单查询或非 SELECT 语句。
ASP 示例(插入记录):
<%
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb"
conn.Execute "INSERT INTO Customers (CustomerID, CompanyName) VALUES ('XYZ', 'XYZ Corp')"
Response.Write "插入成功!"
conn.Close
Set conn = Nothing
%>
- 关键点:
- 返回受影响行数(可选:
conn.Execute sql, affectedRows
)。 - 不适合复杂查询(推荐 Recordset 或 Command)。
3. 使用 Command 对象(参数化查询)
参数化查询防止 SQL 注入,适合动态输入。
ASP 示例(参数化查询):
<%
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 * FROM Customers WHERE Country=?"
Set param = cmd.CreateParameter("@Country", 200, 1, 50, "USA") ' adVarChar
cmd.Parameters.Append param
Set rs = cmd.Execute
Do Until rs.EOF
Response.Write rs("CompanyName") & "<br>"
rs.MoveNext
Loop
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
%>
- 关键点:
adVarChar=200
:指定参数类型。- 更安全,避免拼接 SQL 字符串。
4. 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")
rs = conn.Execute("SELECT CompanyName, ContactName FROM Customers WHERE Country='USA'")[0]
while not rs.EOF:
print(str(rs.Fields("CompanyName").Value))
rs.MoveNext()
rs.Close()
conn.Close()
- 关键点:
conn.Execute
返回元组,[0]
是 Recordset。- 使用
str()
格式化输出(参考str()
vsrepr()
)。
示例:参数化查询
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 * FROM Customers WHERE Country=?"
cmd.Parameters.Append(cmd.CreateParameter("Country", 200, 1, 50, "USA"))
rs = cmd.Execute()[0]
while not rs.EOF:
print(str(rs.Fields("CompanyName").Value))
rs.MoveNext()
rs.Close()
conn.Close()
三、结合上下文的应用
- 结合 REST API:
- 返回 JSON 格式的查询结果。
asp <% Response.ContentType = "application/json" Set conn = Server.CreateObject("ADODB.Connection") conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Northwind.mdb" Set rs = Server.CreateObject("ADODB.Recordset") rs.Open "SELECT CompanyName, ContactName FROM Customers", conn 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 %>
- Python(Flask):
from flask import Flask, jsonify import win32com.client app = Flask(__name__) @app.route('/customers') def get_customers(): conn = win32com.client.Dispatch("ADODB.Connection") conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb") rs = conn.Execute("SELECT CompanyName, ContactName FROM Customers")[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 页面(ADO 查询生成)。
python from selenium.webdriver import Chrome driver = Chrome() driver.get('http://localhost/test.asp') # ASP 使用 ADO 查询 print(driver.find_element(By.TAG_NAME, 'body').text) driver.quit()
- 结合 Linux Cron(Windows 任务计划程序):
- 定时运行查询脚本,输出到文件。
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") rs = conn.Execute("SELECT CompanyName FROM Customers")[0] with open('customers.txt', 'w') as f: for _ in tqdm(range(rs.RecordCount), desc="Querying"): if not rs.EOF: f.write(f"{str(rs.Fields('CompanyName').Value)}\n") rs.MoveNext() conn.Close()
- 保存为
ado_query.py
,通过 Windows 任务计划程序运行。
- 保存为
- 结合 Traefik:
- Traefik 代理 ASP 网站(ADO 查询提供数据)。
yaml services: asp: image: my-asp-app labels: - "traefik.http.routers.asp.rule=Host(`asp.example.com`)" - "traefik.http.routers.asp.entrypoints=websecure"
- 结合列表推导式:
- 处理查询结果。
python import win32com.client conn = win32com.client.Dispatch("ADODB.Connection") conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb") rs = conn.Execute("SELECT CompanyName FROM Customers")[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
:
- 检查查询结果:
python if rs.State == 1: # 值比较 print("Recordset open") if rs is not None: # 身份比较 print("Recordset exists")
- 结合
str()
和repr()
:
- 格式化输出:
python while not rs.EOF: print(str(rs.Fields("CompanyName").Value)) # 用户友好 print(repr(rs.Fields("CompanyName").Value)) # 调试 rs.MoveNext()
四、注意事项
- SQL 注入:
- 避免直接拼接用户输入,使用参数化查询(Command 对象)。
- 错误示例:
rs.Open "SELECT * FROM Customers WHERE Country='" & Request("country") & "'", conn
(易受注入攻击)。
- 性能优化:
- 使用
SELECT column1, column2
而非SELECT *
。 - 设置客户端游标(
rs.CursorLocation = 3
)支持RecordCount
。 - 分页查询(如
SELECT TOP 10
)。
- 错误处理:
- ASP:
asp On Error Resume Next rs.Open "SELECT * FROM NonExistentTable", conn If Err.Number <> 0 Then Response.Write "错误:" & Err.Description
- Python:
python try: rs = conn.Execute("SELECT * FROM NonExistentTable")[0] except Exception as e: print(f"Error: {e}")
- 调试(类似 console.log):
- ASP:
Response.Write rs.Fields(0).Value
. - Python:
print(repr(rs.Fields))
.
- 现代替代:
- Python:
pyodbc
或sqlalchemy
。 - .NET:ADO.NET 或 Entity Framework.
五、总结
- ADO 查询:通过 Recordset、Connection.Execute 或 Command 执行 SQL,获取或修改数据。
- 关键方式:
- Recordset.Open:简单 SELECT。
- Connection.Execute:非 SELECT 或简单查询。
- Command.Execute:参数化查询,安全高效。
- 结合上下文:
- REST API:返回 JSON。
- ChromeDriver:测试查询结果页面。
- Cron:定时查询。
- Traefik:代理 ASP 服务。
- 列表推导式:处理查询结果。
- 调试:使用
Response.Write
(ASP)或print(repr())
(Python)。
如果需要特定查询示例(如复杂 JOIN、分页)、存储过程调用或调试帮助,请提供更多细节!