存储 URL 到 MySQL
序言
如果无法读写数据库,那么一门编程语言的实用性将会大打折扣。好在,SWI-Prolog 对这方面也提供了支持,接下来就这方面进行讲解。
连接 MySQL
查阅 SWI-Prolog 的文档可以看到,如果要读取 MySQL,可以使用这几个谓词:
odbc_driver_connect
,用来连接数据库;odbc_query
,执行查询的 SQL,获取结果;odbc_disconnect
,断开数据库连接。
一段查询 MySQL 版本号信息的示例代码如下
:- use_module(library(odbc), [odbc_disconnect/1, odbc_driver_connect/3, odbc_query/3]).
:- initialization(main, main).
main(_) :-
Dsn = "DRIVER={/usr/local/mysql-connector-odbc-8.0.33-macos13-x86-64bit/lib/libmyodbc8a.so};String Types=Unicode;password=1234567;port=3306;server=localhost;user=shorten",
odbc_driver_connect(Dsn, Connection, []),
Sql = "SELECT VERSION()",
odbc_query(Connection, Sql, row(Version)),
odbc_disconnect(Connection),
format("Version is ~s~n", [Version]).
效果如下图所示
MySQL ODBC 驱动
MySQL 的 ODBC 驱动文件需要自己安装。先到这里下载
安装完毕后,通过iODBC Administrator64
可以看到驱动的具体文件路径
这样就获得了驱动文件的具体路径,可以用到Dsn
中了。
读写 MySQL
假设用于存储短链信息的表名为t_short_url
,其表结构如下
CREATE TABLE `t_short_url` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`url` VARCHAR(256) NOT NULL COMMENT '短链对应的原始链接',
`ctime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`mtime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE INDEX `ux__url` (`url`)
) AUTO_INCREMENT=1000001;
那么可以像下面这样子改写谓词url_to_id
,使其从基于文件变成基于 MySQL 来存储短链信息。
:- module(url_to_id, [url_to_id/2]).
:- use_module(library(odbc), [odbc_disconnect/1, odbc_driver_connect/3, odbc_query/3]).
% 读写文件来管理短链。
url_to_id(Url, Id) :-
string(Url),
var(Id), % Id 不再需要由外部实例化,因此这里要求其为变量。
% 连接数据库。
Dsn = "DRIVER={/usr/local/mysql-connector-odbc-8.0.33-macos13-x86-64bit/lib/libmyodbc8a.so};String Types=Unicode;password=1234567;port=3306;server=localhost;user=shorten",
odbc_driver_connect(Dsn, Connection, []),
% 用参数化来构造 INSERT 语句。
odbc_prepare(Connection, 'INSERT INTO `test`.`t_short_url` SET `url` = ?', [default], Statement),
odbc_execute(Statement, [Url]),
% 获取新行的 id 列的值。
odbc_query(Connection, 'SELECT LAST_INSERT_ID()', row(Id)),
% 断开连接。
odbc_disconnect(Connection).
url_to_id(Url, Id) :-
var(Url),
integer(Id),
% 连接数据库。
Dsn = "DRIVER={/usr/local/mysql-connector-odbc-8.0.33-macos13-x86-64bit/lib/libmyodbc8a.so};String Types=Unicode;password=1234567;port=3306;server=localhost;user=shorten",
odbc_driver_connect(Dsn, Connection, []),
% 在输入安全的情况下直接拼接 SQL 字符串。
format(string(Sql), 'SELECT `url` FROM `test`.`t_short_url` WHERE `id` = ~d', [Id]),
% 获取给定 ID 的行的原始 URL。
odbc_query(Connection, Sql, row(Url)),
% 断开连接。
odbc_disconnect(Connection).
可以单独测试这个模块的效果,如下图所示
而在调用谓词url_to_id
的位置,则不再需要事先计算好Id
的值了,将下列代码删除
% 姑且用当前时间戳来作为 ID。
get_time(TimeStamp),
Id is truncate(TimeStamp),
然后 HTTP 服务便可以照常运作了。