2、SQL查询语句实战:SELECT语句在Intouch中的使用、WHERE条件过滤、ORDER BY排序

好,咱们直接进入正题。上一章我们把数据库表结构搭好了,也把Intouch和SQL Server连上了。但说实话,连上只是第一步,真正干活的是怎么把数据查出来

这一章,我就带你手把手搞定SELECT语句。别小看它,我见过太多项目,就因为查询写得烂,导致画面卡死、报表出不来。嗯,咱们从最基础的开始。

2.1 SELECT语句:从表中拿数据

SELECT,说白了就是「我要看什么」。它的基本骨架很简单:

SELECT 列名 FROM 表名

比如,我想看历史报警表里的所有记录:

SELECT * FROM AlarmHistory

这里的*是通配符,代表「所有列」。但我在实际项目中,几乎不用*。为什么?

有一次,我在一个水处理项目里,用*查报警表,结果画面卡了十几秒。后来一查,那张表有30多列,其中几列存的是大段的文本描述。你想想看,每次查询都拉回这么多没用的数据,性能能好吗?

我的习惯:只查你需要的列。比如只要报警时间、标签名和报警值,就写成:
SELECT AlarmTime, TagName, AlarmValue FROM AlarmHistory

2.2 WHERE条件过滤:只拿你想要的

不加条件的SELECT,等于把整张表倒出来。这在Intouch里基本没有意义——你不可能让操作员看几百万条历史记录。

WHERE子句就是干这个的:加条件,筛数据

2.2.1 基本比较运算符

运算符 含义 示例
= 等于 WHERE TagName = 'Tank_Level'
<> 或 != 不等于 WHERE AlarmValue <> 0
> 大于 WHERE AlarmValue > 100
< 小于 WHERE AlarmValue < 50
BETWEEN 在范围内 WHERE AlarmValue BETWEEN 50 AND 100
LIKE 模糊匹配 WHERE TagName LIKE 'Tank%'

举个例子。我想查某个液位标签在2024年1月1日之后的所有报警:

SELECT AlarmTime, TagName, AlarmValue, AlarmStatus
FROM AlarmHistory
WHERE TagName = 'Tank_Level_01'
  AND AlarmTime >= '2024-01-01 00:00:00'
注意:日期格式一定要和数据库里的格式一致。我曾经在项目里吃过这个亏——SQL Server默认日期格式是YYYY-MM-DD,但Intouch传过来的字符串是MM/DD/YYYY,结果查出来全是空的。排查了半天,最后发现是格式不匹配。

2.2.2 组合条件:AND 和 OR

实际项目中,很少只用一个条件。比如我想查「液位高报警」且「值大于80」的记录:

SELECT * FROM AlarmHistory
WHERE TagName = 'Tank_Level_01'
  AND AlarmValue > 80
  AND AlarmStatus = 'Active'

注意,AND的优先级高于OR。如果你混用,最好加括号。我见过有人写:

-- 这样写容易有歧义
WHERE TagName = 'Tank_01' OR TagName = 'Tank_02' AND AlarmValue > 100

你猜它先执行哪个?嗯,它会先执行AND,再执行OR。所以上面这句,实际等价于:

WHERE TagName = 'Tank_01' OR (TagName = 'Tank_02' AND AlarmValue > 100)

这很可能不是你想要的结果。我的建议是:永远用括号明确优先级

WHERE (TagName = 'Tank_01' OR TagName = 'Tank_02')
  AND AlarmValue > 100

2.3 ORDER BY排序:让数据排好队

查出来的数据默认是按插入顺序排列的。但你想看最新的报警在最上面,怎么办?

用ORDER BY。

SELECT AlarmTime, TagName, AlarmValue
FROM AlarmHistory
WHERE TagName = 'Tank_Level_01'
ORDER BY AlarmTime DESC

DESC表示降序(最新的在最上面),ASC表示升序(默认)。

也可以按多列排序。比如先按标签名排,再按时间排:

SELECT * FROM AlarmHistory
ORDER BY TagName ASC, AlarmTime DESC
性能提醒:ORDER BY会消耗额外的资源。如果你查几万条数据再排序,画面可能会卡。我一般建议:先WHERE过滤到几百条以内,再ORDER BY

2.4 在Intouch中执行SELECT

好了,SQL语句写好了,怎么在Intouch里用?

Intouch通过ODBC连接数据库,用SQLSelect()函数执行查询。基本流程是:

  1. SQLConnect()建立连接
  2. SQLSelect()执行查询
  3. SQLFirst() / SQLNext()遍历结果
  4. SQLDisconnect()断开连接

举个例子,在按钮脚本里写:

// 建立连接
SQLConnect(ConnectionId, "DSN=MySCADA;UID=sa;PWD=123456");

// 执行查询
SQLSelect(ConnectionId, "SELECT AlarmTime, TagName, AlarmValue FROM AlarmHistory WHERE TagName = 'Tank_Level' ORDER BY AlarmTime DESC");

// 获取第一条记录
SQLFirst(ConnectionId);

// 把结果读到内存标签里
TagName = SQLResult(ConnectionId, 2);  // 第2列
AlarmValue = SQLResult(ConnectionId, 3);  // 第3列

// 循环读取下一条
WHILE SQLNext(ConnectionId) == 1 DO
    TagName = SQLResult(ConnectionId, 2);
    AlarmValue = SQLResult(ConnectionId, 3);
ENDWHILE;

// 断开连接
SQLDisconnect(ConnectionId);
避坑指南:我曾经在项目里忘了调用SQLDisconnect(),结果数据库连接数爆满,导致其他客户端连不上。后来我养成了习惯:每次查询完,立刻断开连接。如果脚本里有多处查询,可以用一个全局变量管理连接ID。

2.5 本章知识体系

下面这张图,帮你理清SELECT语句的核心逻辑:

SELECT查询语句核心流程 SELECT 列名 FROM 表名 WHERE 条件过滤 ORDER BY 排序 关键说明 • 只查需要的列,别用 * • WHERE 用 AND/OR 组合条件 • 日期格式要匹配数据库 • ORDER BY 先过滤再排序 • Intouch 用 SQLSelect() 执行 • 记得断开连接 💡 我的经验: 先写SQL在SSMS里测试通过 再复制到Intouch脚本中

2.6 实战小贴士

最后,分享几个我在项目中总结的实用技巧:

  • 先测试再部署:我习惯先在SQL Server Management Studio里把SELECT语句跑通,确认结果正确,再复制到Intouch脚本里。这样能避免很多低级错误。
  • 参数化查询:如果条件里的值是变量(比如操作员选择的日期),别直接拼字符串。用SQLSetStatement()配合参数,既安全又高效。
  • 分页查询:如果数据量很大(比如几十万条),用TOPOFFSET FETCH做分页。别一次全查出来,Intouch画面扛不住。

一句话总结:SELECT是SQL的基石。WHERE帮你精准定位,ORDER BY让数据井然有序。在Intouch里用好它们,你的画面会又快又准。


公众号:蓝海资料掘金营,微信deep3321