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.