GLPK/Table 语句
Table 语句可用于将数据从外部数据源读入模型对象,包括集合和参数。Table 语句还可用于将模型结果写回外部数据源。当前为ODBC数据库,尤其是MySQL数据库,CSV文件,以及dBase文件提供驱动程序。
GLPK 官方文档文件doc/gmpl.pdf(在 GLPK 4.45 之前doc/tables.pdf) 包含 GMPL 表功能的完整参考。请参阅获取 GLPK。此页面仅提供指针和示例。
从 4.45 版开始,以下信息丢失了
字段名由字母 [A-Z,a-z] 和数字 [0-9] 字符组成,区分大小写。它不需要是唯一的[1]。
逗号分隔值 (CSV) 文件的格式在RFC 4180[1]中描述。
对于 CSV 文件,驱动程序标识符为“CSV”。table OUT 语句将完全替换任何现有文件。
CSV 表驱动程序具有以下内置限制
- 列数必须小于或等于 50。
- 每个值的长度必须小于或等于 100 个字符。
以下示例展示了 CSV 文件的读取和写入
# test1.mod writes CSV file set I := {1..300}; set J := {1..20}; set K := {1..100}; param x{I,J,K} := Uniform01(); table tout {i in I, j in J, k in K} OUT "CSV" "test.csv" : i, j, k, x[i,j,k]; end;
# test2.mod reads CSV file set I, dimen 3; param x{I}; table tin IN "CSV" "test.csv" : I <- [i,j,k], x; printf "Number of values: %d\n", card(I); printf "Average value: %f\n", (sum{(i,j,k) in I} x[i,j,k]) / card(I); end;
对于dBase文件,驱动程序标识符为“xBASE”。table OUT 语句将完全替换任何现有文件。
dBase 表驱动程序具有以下内置限制
- 列数必须小于或等于 50。
- 每个值的长度必须小于或等于 100 个字符。
对于ODBC数据库连接,驱动程序标识符为“ODBC”。对于本机MySQL数据库连接,驱动程序标识符为“MySQL”。
请注意,table UPDATE 和 table INSERT 语句必须后跟 table OUT 语句才能生效(如执行 SQL部分所述)。
使用 MySQL 表驱动程序时,table 语句可以充分利用连接的数据库提供的SQL命令。MySQL REPLACE 语句是 SQL 的非标准扩展,它意味着随后的 table OUT 语句。
table IN 语句与其他 SQL 语句结合使用,可用于从关系数据库中选择数据。例如
set I, dimen 2; param st{I}; table t IN 'ODBC' 'FILEDSN=supply.dsn' 'SELECT product, period, quantity' ' FROM stock' : I <- [product, period], st ~ quantity;
不用 SELECT 语句,可以提供表名。在这种情况下,将选择整个表。
set I, dimen 2; param st{I}; table t IN 'ODBC' 'FILEDSN=supply.dsn' 'stock' : I <- [product, period], st ~ quantity;
SELECT 语句(或表名)可以由其他 SQL 语句作为前缀
set I, dimen 2; param st{I}; table t IN 'ODBC' 'FILEDSN=supply.dsn' 'DROP TABLE IF EXISTS result;' 'CREATE TABLE result (' ' product TEXT(40),' ' period INTEGER,' ' quantity FLOAT,' ' PRIMARY KEY ( product(40), period ) );' 'SELECT product, period, quantity' ' FROM stock' : I <- [product, period], st ~ quantity;
可以将 SQL 语句拆分为多个字符串以克服 GLPK 中100 个字符单行字符串长度限制。在这种情况下,SQL 语句的终止由在多行调用(如上所示)的最后一个字符中存在未加引号的分号来指示。
从 GLPK 4.44 开始,GLPK 使用 ODBC 和 MySQL 驱动程序时,会自动从字符串中修剪尾随空格 (0x20) 字符。strtrim()函数。
table OUT 语句与其他 SQL 语句结合使用,可用于在关系数据库中插入、更新或删除记录。
INSERT 语句可用于将记录插入关系数据库。例如
table t {p in P, t in T} OUT 'ODBC' 'FILEDSN=supply.dsn' 'INSERT INTO stock' ' ( product, period, quantity) ' ' VALUES (?,?,?)' : p, t, st[p, t];
如果最后一个 SQL 语句不包含作为值占位符的问号,则需要表名。该表名和提供的列名将用于构建 INSERT 语句。
table t {p in P, t in T} OUT 'ODBC' 'FILEDSN=supply.dsn' 'stock': p ~ product, t ~ period, st[p, t] ~ quantity;
迭代的最终 SQL 语句可以由其他 SQL 语句作为前缀
table t {p in P, t in T} OUT 'ODBC' 'FILEDSN=supply.dsn' 'DELETE FROM stock;' 'INSERT INTO stock' ' ( product, period, quantity) ' ' VALUES (?,?,?)' : p, t, st[p, t];
这种策略可以用于避免重复插入。
可以发出 INSERT 以外的语句。例如,UPDATE 语句可用于更新关系数据库中的记录。例如
table t {p in P, t in T} OUT 'ODBC' 'FILEDSN=supply.dsn' 'UPDATE stock' ' SET quantity = ?' ' WHERE' ' product = ? AND period = ?;' : st[p, t], p, t;
DELETE 语句可用于从关系数据库中删除记录。例如
table t {p in P, t in T} OUT 'ODBC' 'FILEDSN=supply.dsn' 'DELETE FROM stock' ' WHERE' ' product = ? AND period = ?;' : p, t;
目前,GMPL 语言中的 SQL 支持仅允许在“table IN”和“table OUT”语句块中发出 SQL 命令。
在“table IN”块中,最终的 SELECT 语句(或表名)可以由任意数量的准备 SQL 语句作为前缀。
在“table OUT”块中,迭代域的最终 INSERT/DELETE/UPDATE 语句可以由任意数量的准备 SQL 语句作为前缀。
为了将准备语句与数据库 I/O 完全分开,可以使用虚拟输出语句
table prep {i in 1..1} OUT 'ODBC' 'DSN=glpk;UID=glpk;PWD=gnu' # The preparatory SQL statement(s) follow 'DELETE FROM stock;' # The next SQL statement is needed to satisfy the GMPL syntax. 'SELECT ?;' : i;
在 4.45 版之前的 GLPK 版本中,处理 table 语句时可能会遇到内存溢出错误。该问题在此主题中进行了描述,现在已解决。
- ↑ Y. Shafranovich (October 2005). "Common Format and MIME Type for Comma-Separated Values (CSV) Files".