GLPK/ODBC
开放式数据库连接 (ODBC) 为关系型数据库管理系统提供标准化接口。GLPK 使用 ODBC 接口与关系型数据库和电子表格进行通信,这些数据库和电子表格包含运行时优化模型数据。
ODBC 需要安装的驱动程序管理器 *和* 数据库特定的 ODBC 连接。
在官方 GLPK 文档文件中doc/gmpl.pdf包含了关于从关系型数据库和电子表格使用表格的 *完整参考* (GLPK 4.27 - 4.44:参见doc/tables.pdf)。因此,此处不会重复大部分内容。请参阅获取 GLPK。
使用表格语句来访问特定的 ODBC 数据库
table name alias IN 'ODBC' conn sql . . . sql : set <- [ fld , . . . , fld ] , par ~ fld , . . . , par ~ fld ; table name alias domain OUT 'ODBC' conn sql . . . sql : expr ~ fld , . . . , expr ~ fld ;
根据当前的编程,GMPL 中的字符串限制为 100 个字符。此限制很容易在表格语句中达到,无论是
- 连接字符串 (conn) 语句,还是
- SQL (sql) 语句。
一种解决方案是使用数据集名称 (DSN) 连接字符串,只包含密码和用户详细信息
'DSN=glpk;UID=glpk;PWD=gnu'
如果这不够灵活,可以使用文件 DSN(见后文)。
SQL 语句可以分布在多行。SQL 语句最后一行最后一个字符必须是分号 (;)。各个字符串用空格隔开,在发送到 SQL 命令处理器之前进行连接。例如
table ta {(i, j) in {i1 in 1..9} cross {i2 in 1..9}} OUT 'ODBC' 'DSN=glpk;UID=glpk;PWD=gnu' 'DELETE FROM sudoku_solution' # line 1 of SQL statement 1 'WHERE ID = ' & id & ';' # line 2 of SQL statement 1 'INSERT INTO sudoku_solution' # line 1 of SQL statement 2 '(ID, COL, LIN, VAL)' # line 2 of SQL statement 2 'VALUES(?, ?, ?, ?);' : # line 3 of SQL statement 2 id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL;
可以安全地增加MAX_LENGTH文件中的宏src/glpmpl.h从 100 到 240,以允许处理更长的符号值,包括传递给 ODBC 驱动程序的控制字符串。缺点是,您的模型可能不再适用于 GLPK 的默认构建。这个问题也在这个2012 年初的帖子中讨论。
GLPK 的默认构建*没有*启用MySQL 表驱动程序。要使用此数据库,您需要按如下方式配置 GLPK
./configure --enable-dl --enable-mysql ...
然后运行make像往常一样。如果您尝试在没有此支持的情况下访问 MySQL,GLPK 将报告
MySQL table driver not supported
如果您运行的是 64 位 Windows 7,并且希望使用 GLPSOL 可执行文件从MySQL 数据库中提取数据,解决您在 MathProg 中的问题.mod文件,然后将解决方案写回您的数据库,请尝试以下操作(已确认 2011 年 9 月使用 GLPK 4.47)。您首先需要
- 64 位 MySQL Community Server 5.5.16 for Windows (x86, 64 位) — 下载
- 64 位 MySQL ODBC Connector 5.1.8 for Windows (x86, 64 位) — 下载
- 64 位 GLPK 可执行文件 — 请参阅获取Windows 可执行文件
使用以下方法设置 64 位数据源c:\Windows\system32\odbcad32.exe如以下所述,访问您的 MySQL 数据库存。
以下 MathProg 代码展示了一种在您的模型中填充 MathProg *集* 的方法
/* Import finished goods set from MySQL database */ table t IN "iODBC" 'DSN=glpk;UID=glpk;PWD=glpk' 'export_finished_good' : FIN <- [ FinishedGood ];
在上面的例子中,export_finished_good和FinishedGood分别是来自 MySQL 数据库的相关表名和字段名。以及FIN是您想要用数据库中的数据填充的 MathProg 集。
以下 MathProg 代码展示了一种在您的模型中填充二维 MathProg *数组* 的方法
/* Import finished good demand from MySQL database */ table t IN "iODBC" 'DSN=glpk;UID=glpk;PWD=glpk' 'export_finished_good_demand' : [ FinishedGood, PERIOD ], FinDem ~ DEMAND;
在此示例中,读取了每个时期特定商品的需求。数据来自 MySQL 表export_finished_good_demand并用于填充 MathProg 数组FinDem,其维度由FIN和TIM决定 - 它们分别表示成品和时间段的两个集合。保存成品列表的字段名为FinishedGood,保存时间段列表的字段名为PERIOD,保存每个时期每个成品需求的字段名为DEMAND。接收此数据的 MathProg 数组之前声明为FinDem{FIN, TIM}.
ODBC 是Windows 的组成部分。对于Linux,两个开源项目提供了 ODBC API 的主要实现
- iODBC — www.iodbc.org
- unixODBC — www.unixodbc.org。
ODBC 连接器使用的库存储在配置文件中/etc/odbcinst.ini。例如,如果在 Linux 上使用MySQL 关系型数据库管理系统
[MySQL] Description = ODBC for MySQL Driver = /usr/lib/odbc/libmyodbc.so Setup = /usr/lib/odbc/libodbcmyS.so UsageCount = 1 CPTimeout = CPReuse =
Windows 在注册表项下存储相同的信息HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI.
数据集名称 (DSN) 是描述关系型数据库访问数据的结构。存在三种类型的 DSN
- 系统 DSN — 存储在/etc/odbc.ini在 Linux 下,或在 Windows 注册表项中HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI
- 用户 DSN — 存储在~/.odbc.ini在 Linux 下,或在 Windows 注册表项中HKEY_CURRENT_USER\Software\ODBC\ODBC.INI
- 文件 DSN
iODBC 和 unixODBC 在 Linux 下提供 DSN 编辑器。
如果使用 32 位 Windows,请调用c:\WINDOWS\system32\odbcad32.exe用于编辑数据源。如果使用 64 位 Windows,则可以存在 32 位和 64 位数据源。要编辑 64 位数据源,请调用c:\WINDOWS\system32\odbcad32.exe,要编辑 32 位数据源,请调用c:\WINDOWS\syswow64\odbcad32.exe.
文件 DSN 在单个文件中存储单个 DSN 的描述,例如
[ODBC] DRIVER=Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) DBQ=.\sudoku.xlsx
对于文件 DSN,Windows 默认情况下使用路径c:\Program Files\Common Files\ODBC\Data Sources.
DSN 中的密码未加密,因此出于安全原因,*不要将* DSN 信息存储在不安全的机器上。
使用 ODBC 接口的应用程序必须将数据库连接的访问数据作为连接字符串传递给 ODBC API。
连接字符串可以*可选地*引用 DSN,在*覆盖*过程中覆盖某些(或全部)字段。
以下连接字符串引用名为glpk的 DSN,并覆盖当前用户名和密码
DSN=glpk;UID=myuser;PWD=mypassword
以下连接字符串在应用程序路径内使用文件 DSN
FileDSN=.\sudoku_excel.dsn
无 DSN 连接字符串指定驱动程序和驱动程序特定的参数,例如
DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb);DBQ=.\sudoku.xlsx
Microsoft Access 是微软办公套件中的一部分,它是一个关系型数据库应用程序。 Access 的驱动程序包含在可下载的“2007 Office System Driver: Data Connectivity Components”和“Microsoft Access Database Engine 2010 Redistributable”资源中。
对于 Access 2007 和 2010,一个有效的无 DSN 连接字符串的示例是
DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};dbq=.\glpk.accdb
对于早期版本的 Access,一个有效的无 DSN 连接字符串的示例是
DRIVER={Microsoft Access Driver (*.mdb)};dbq=.\glpk.mdb
机器架构
[edit | edit source]Microsoft Access 2007 是一个 32 位应用程序,如果您希望使用 ODBC 连接到 Access,则必须使用 32 位版本的 GLPK。 如果您需要使用 64 位版本的 GLPK,那么您需要安装 Access 的 64 位 ODBC 连接器。 它包含在 64 位版本的“Microsoft Access Database Engine 2010 Redistributable”或 64 位版本的 Microsoft Office 2010 中。 Microsoft Office 的 32 位和 64 位安装是互斥的——如果您想使用 64 位 Access,则需要删除 32 位 Access。
SQL 语法
[edit | edit source]以下 SQL 语法适用于编写与 Access 交互的 GMPL 模型
- 字符串必须用撇号括起来(例如'Value'),而不是用引号括起来(例如"Value")
- 要将 DateTime(时间戳)字段转换为 GLPK 使用的时间表示形式,请调用 Access 函数
DateDiff
[1] - 列别名不能是保留名称,例如
time
- 包含空格的列名必须用方括号括起来(例如[Product Code]).
例如
set ProdTime, dimen 2; param sales{ProdTime}; table products_table IN "ODBC" 'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};dbq=.\sales.accdb' 'SELECT' ' [Product Code] AS p,' ' DateDiff(''s'', #01/01/1970#, Period) AS t,' ' [Net Sales] AS s' 'FROM [Historic Sales]' 'WHERE [Product Text] = ''Unskimmed Milk'';' : ProdTime <- [p, t], sales ~ s;
可以在 [2] 中找到 Access 2007 函数列表。
Microsoft Excel
[edit | edit source]Microsoft Excel 是微软提供的电子表格程序。 Excel 的驱动程序包含在可下载的“2007 Office System Driver: Data Connectivity Components”和“Microsoft Access Database Engine 2010 Redistributable”资源中。“Microsoft Access Database Engine 2010 Redistributable”资源包含 32 位和 64 位版本。 使用与您拥有的 GLPK 库匹配的版本。
以下连接字符串使用文件无 DSN 连接到 Microsoft Excel
DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb);DBQ=.\sudoku.xlsx;READONLY=FALSE
默认情况下,对 Excel 的 ODBC 连接是只读的。 [3] 您必须设置ReadOnly到False才能将数据写回 Excel。
Excel ODBC 驱动程序不支持 DELETE、UPDATE 或 ALTER TABLE 语句。 [4]。 本质上,它只能追加新行。
以下字段受支持
字段 | 意义 |
---|---|
驱动程序 | ODBC 连接驱动程序 |
DBQ | Excel 文件名 |
FirstRowHasNames | 1 = true,0 = false |
ReadOnly | False = 可写入 |
在下面的示例中,集合 'orders' 的条目被写入 Excel 工作簿中名为 'result' 的区域out.xlsx。 为了使示例能够正常工作,Excel 工作簿out.xlsx必须存在,并且必须包含一个名为 'result' 的命名区域,该区域包含 3 列。
param tableName, symbolic; set orders, dimen 3; solve; table result {(p, o, q) in orders} OUT "ODBC" 'DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};' & 'DBQ=.\out.xlsx;READONLY=FALSE' 'DROP TABLE [' & tableName & '];' 'CREATE TABLE [' & tableName & ']' '(Product CHAR(20), OrderNumber CHAR(10), Quantity DOUBLE);' 'INSERT INTO [' & tableName & ']' '(Product, OrderNumber, Quantity)' 'VALUES(?, ?, ?);' : p, o, q; data; param tableName := 'result'; set orders := 'Full Milk', '0600000101', 10., 'UHT Milk', '0600000102', 16., 'Semi Skimmed Milk', '0600000103', 14., 'UHT Milk', '0600000104', 36.; end;
有关更多信息,请在 "Excel" 上搜索help-glpk邮件列表。
执行一系列不写入记录的 SQL 语句
[edit | edit source]您可能希望执行一个或多个不写入记录的 SQL 语句。 例如,您可能希望从表中删除所有记录。 这可能很棘手,因为如果最后一行不包含“?”,GMPL 将假设它命名了一个表,并执行一个多余的 INSERT INTO。 一个解决方法是在最后一个语句中编码一个不必要的“?”。 例如
table DeleteRecords {x in 1..1} OUT 'ODBC' 'DSN=glpk;UID=glpk;PWD=gnu' 'DELETE FROM sudoku_solution WHERE ?=?' : x, x;
ODBC 陷阱
[edit | edit source]如果要从数据库读取浮点数据,GLPSOL 只能在数据包含一个点“.”作为小数点分隔符时才能处理它。 因此,ODBC 驱动程序必须确保以这种格式返回数据。 在 Oracle 11g 数据库的情况下,将环境变量 NLS_LANG 设置为“American_America.WE8ISO8859P1”,然后数据库将返回“.”作为数字数据的十进制分隔符(ODBC 驱动程序读取该变量并相应地格式化数据)。
在 SELECT 语句中使用“*”必须谨慎处理。 GMPL 需要在 SQL 语句中具有与 GMPL 表语句中引用的完全相同的列名。 SQL 列与 GMPL 字段名称之间没有自动匹配。
根据 SQL 实现和操作系统,列名可能区分大小写。 [5].
参考文献
[edit | edit source]- ↑ "DateDiff Function". Microsoft Corporation. Retrieved 26 June 2011.
- ↑ "Access 2007 Help and How-to - Macros and programmability - Functions (alphabetical)". Microsoft Corporation. Retrieved 26 June 2011.
- ↑ "257819 How To Use ADO with Excel Data from Visual Basic or VBA". Microsoft Corporation. Retrieved 28 December 2010.
- ↑ "INF: Excel ODBC Driver and Text ODBC Driver Notes". Retrieved 30 May 2013.
- ↑ "Identifier Case Sensitivity". Oracle. Retrieved 2012-02-27.