macOS上的ODBC-利用unixODBC连接PostgreSQL与SQLite并进行数据迁移
安装UnixODBC
& PSQLODBC driver for UnixODBC
$ brew install psqlodbc
Updating Homebrew...
==> Installing dependencies for psqlodbc: postgresql, unixodbc
==> Installing psqlodbc dependency: postgresql
==> Downloading https://homebrew.bintray.com/bottles/postgresql-9.6.3.sierra.bottle.ta
######################################################################## 100.0%
==> Pouring postgresql-9.6.3.sierra.bottle.tar.gz
==> Using the sandbox
==> /usr/local/Cellar/postgresql/9.6.3/bin/initdb /usr/local/var/postgres
==> Caveats
If builds of PostgreSQL 9 are failing and you have version 8.x installed,
you may need to remove the previous version first. See:
https://github.com/Homebrew/legacy-homebrew/issues/2510
To migrate existing data from a previous major version (pre-9.0) of PostgreSQL, see:
https://www.postgresql.org/docs/9.6/static/upgrading.html
To migrate existing data from a previous minor version (9.0-9.5) of PostgreSQL, see:
https://www.postgresql.org/docs/9.6/static/pgupgrade.html
You will need your previous PostgreSQL installation from brew to perform `pg_upgrade`.
Do not run `brew cleanup postgresql` until you have performed the migration.
To have launchd start postgresql now and restart at login:
brew services start postgresql
Or, if you don't want/need a background service you can just run:
pg_ctl -D /usr/local/var/postgres start
==> Summary
�� /usr/local/Cellar/postgresql/9.6.3: 3,259 files, 36.6MB
==> Installing psqlodbc dependency: unixodbc
==> Downloading https://homebrew.bintray.com/bottles/unixodbc-2.3.4.sierra.bottle.1.ta
######################################################################## 100.0%
==> Pouring unixodbc-2.3.4.sierra.bottle.1.tar.gz
�� /usr/local/Cellar/unixodbc/2.3.4: 43 files, 2.0MB
==> Installing psqlodbc
==> Downloading https://homebrew.bintray.com/bottles/psqlodbc-09.06.0310.sierra.bottle
######################################################################## 100.0%
==> Pouring psqlodbc-09.06.0310.sierra.bottle.tar.gz
�� /usr/local/Cellar/psqlodbc/09.06.0310: 6 files, 796.1KB
$ brew services start postgresql
==> Successfully started `postgresql` (label: homebrew.mxcl.postgresql)
其中unixODBC
的库在
/usr/local/Cellar/unixodbc/2.3.4
postgreSQLODBC
库在
/usr/local/Cellar/psqlodbc/09.06.0310
配置UnixODBC
查看PSQL
的默认配置
Connection options:
-h, --host=HOSTNAME database server host or socket directory (default: "local socket")
-p, --port=PORT database server port (default: "5432")
-U, --username=USERNAME database user name (default: "He11o_Liu")
-w, --no-password never prompt for password
-W, --password force password prompt (should happen automatically)
配置unix ODBC
odbcinst.ini
[PostgreSQL]
Description=PostgreSQL driver for Linux
Driver=/usr/local/Cellar/psqlodbc/09.06.0310/lib/psqlodbcw.so
Setup=/usr/local/Cellar/psqlodbc/09.06.0310/lib/psqlodbcw.so
UsageCount=1
odbc.ini
[Liu]
Description=Liu
Driver=PostgreSQL
Trace=Yes
TraceFile=sql.log
Database=student
Servername=localhost
UserName=root
Password=
Port=5432
Protocol=6.4
ReadOnly=No
RowVersioning=No
ShowSystemTables=No
ShowOidColumn=No
FakeOidIndex=No
测试UnixODBC
链接PSQL
利用isql
测试UnixODBC
与PSQL
的连接
$ isql -v Liu
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> quit
出现的问题
坑人的Mac
中的动态库dylib
直接链接到目录不能够正常读出。必须手动一个个加上。
书写Makefile
如下
ODBCLIB = /usr/local/Cellar/unixodbc/2.3.4/lib/libodbc.2.dylib /usr/local/Cellar/unixodbc/2.3.4/lib/libodbcinst.2.dylib /usr/local/Cellar/unixodbc/2.3.4/lib/libodbccr.2.dylib
ODBCINC = -I/usr/local/Cellar/unixodbc/2.3.4/include/
all:simple
simple:simple.c
gcc -o simple simple.c $(ODBCLIB) $(ODBCINC)
odbc:odbc.c
gcc -o odbc odbc.c $(ODBCLIB) $(ODBCINC)
clean:
-rm odbc
-rm simple
测试与unixODBC
连接
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
int main() {
SQLHENV env;
char driver[256];
char attr[256];
SQLSMALLINT driver_ret;
SQLSMALLINT attr_ret;
SQLUSMALLINT direction;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
direction = SQL_FETCH_FIRST;
while(SQL_SUCCEEDED(ret = SQLDrivers(env, direction,
(unsigned char *)driver, sizeof(driver), &driver_ret,
(unsigned char *)attr, sizeof(attr), &attr_ret))) {
direction = SQL_FETCH_NEXT;
printf("%s - %s\n", driver, attr);
if (ret == SQL_SUCCESS_WITH_INFO) printf("\tdata truncation\n");
}
}
测试结果如下:
$ ./odbc
PostgreSQL - Description=PostgreSQL driver for Linux
测试ODBC
功能
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <stdio.h>
#include <sqlucode.h>
#include <odbcinst.h>
void ODBC_error ( /* Get and print ODBC error messages */
SQLHENV henv, /* ODBC Environment */
SQLHDBC hdbc, /* ODBC Connection Handle */
SQLHSTMT hstmt) /* ODBC SQL Handle */
{
UCHAR sqlstate[10];
UCHAR errmsg[SQL_MAX_MESSAGE_LENGTH];
SDWORD nativeerr;
SWORD actualmsglen;
RETCODE rc = SQL_SUCCESS;
while ( rc != SQL_NO_DATA_FOUND)
{
rc = SQLError(henv, hdbc, hstmt,
sqlstate, &nativeerr, errmsg,
SQL_MAX_MESSAGE_LENGTH - 1, &actualmsglen);
if (rc == SQL_ERROR) {
printf ("SQLError failed!\n");
return;
}
if (rc != SQL_NO_DATA_FOUND) {
printf ("SQLSTATE = %s\n", sqlstate);
printf ("NATIVE ERROR = %d\n", nativeerr);
errmsg[actualmsglen] = '\0';
printf ("MSG = %s\n\n", errmsg);
}
}
if (hdbc != SQL_NULL_HDBC)
{
SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
}
if (henv != SQL_NULL_HENV)
{
SQLFreeHandle (SQL_HANDLE_ENV, henv);
}
}
int main(void)
{
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc = SQL_NULL_HDBC;
SQLHSTMT hstmt = SQL_NULL_HSTMT;
RETCODE rc = SQL_SUCCESS;
rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (rc != SQL_ERROR)
{
printf("SQLAllocHandle() OK\n");
rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,0);
if (rc != SQL_ERROR)
{
printf("SQLSetEnvAttr() ok\n");
rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
if ( rc != SQL_ERROR)
{
printf("SQLAllocHandle() ok\n");
rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF,0);
if (rc != SQL_ERROR)
{
printf("SQLSetConnectAttr() ok\n");
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
}
}
}
if (rc == SQL_ERROR)
{
ODBC_error (henv, hdbc, hstmt);
}
}
功能测试通过
$ ./simple
SQLAllocHandle() OK
SQLSetEnvAttr() ok
SQLAllocHandle() ok
SQLSetConnectAttr() ok
测试获取全部数据
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
void extract_error(
char *fn,
SQLHANDLE handle,
SQLSMALLINT type)
{
SQLINTEGER i = 0;
SQLINTEGER native;
SQLCHAR state[ 7 ];
SQLCHAR text[256];
SQLSMALLINT len;
SQLRETURN ret;
fprintf(stderr,
"\n"
"The driver reported the following diagnostics whilst running "
"%s\n\n",
fn);
do
{
ret = SQLGetDiagRec(type, handle, ++i, state, &native, text,
sizeof(text), &len );
if (SQL_SUCCEEDED(ret))
printf("%s:%ld:%ld:%s\n", state, i, native, text);
}
while( ret == SQL_SUCCESS );
}
int main()
{
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns; /* number of columns in result-set */
SQLSMALLINT rows; /* number of columns in result-set */
int row = 0;
int j = 0,i = 0;
SQLINTEGER indicator;
char buf[512];
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
/* You will need to change mydsn to one you have created and tested */
ret = SQLDriverConnect(dbc, NULL, "DSN=Liu;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)){ printf("Connected\n");}
/* Allocate a statement handle */
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (ret == -1) { printf("fail\n");}
/* Retrieve a list of tables */
// SQLTables(stmt, NULL, 0, NULL, 0, NULL, 0, "TABLE", SQL_NTS);
ret = SQLExecDirect(stmt, "select * from student", SQL_NTS);
// printf("%d\n",ret);
/* How many columns are there */
SQLNumResultCols(stmt, &columns);
printf("Columns:%d\n",columns);
// /* How many rows are there */
// ret = SQLFetch(stmt);
// ret = SQLRowCount(stmt,&rows);
// printf("%d\n",rows);
/* Loop through the rows in the result-set */
while (SQL_SUCCEEDED(ret = SQLFetch(stmt))){
printf("Row %d\n", row++);
j = 1;
/* Loop through the columns */
while(j <= columns){
i = j;
/* retrieve column data as a string */
ret = SQLGetData(stmt, i, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)){
/* Handle null columns */
if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");
printf("\tColumn %u : %10s len:%d\n",i, buf,indicator);
}
j++;
}
}
}
测试输出如下
$ ./fetch
Connected
Columns:2
Row 0
Column 0 : 0 len:1
Column 0 : stu_0 len:20
Row 1
Column 0 : 1 len:1
Column 0 : stu_1 len:20
Row 2
Column 0 : 2 len:1
Column 0 : stu_2 len:20
Row 3
Column 0 : 3 len:1
Column 0 : stu_3 len:20
Row 4
Column 0 : 4 len:1
Column 0 : stu_4 len:20
Row 5
Column 0 : 5 len:1
Column 0 : stu_5 len:20
测试修改数据
int main()
{
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns; /* number of columns in result-set */
SQLSMALLINT rows; /* number of columns in result-set */
int row = 0;
int j = 0,i = 0;
SQLINTEGER indicator;
char buf[512];
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
/* You will need to change mydsn to one you have created and tested */
ret = SQLDriverConnect(dbc, NULL, "DSN=Liu;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)){ printf("Connected\n");}
/* Allocate a statement handle */
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (ret == -1) { printf("fail\n");}
/* Retrieve a list of tables */
ret = SQLExecDirect(stmt, "update student set sname = 'Liu' where sno = 1;", SQL_NTS);
if (ret == -1) { printf("fail\n");}
ret = SQLExecDirect(stmt, "insert into student values(1010,'test');", SQL_NTS);
if (ret == -1) { printf("fail\n");}
ret = SQLExecDirect(stmt, "delete from student where sno = 1010;", SQL_NTS);
if (ret == -1) { printf("fail\n");}
return 0;
}
连接SQLite3
这个地方很坑
下载SQLiteODBC
$ brew info sqliteodbc
sqliteodbc: stable 0.9995 (bottled)
SQLite ODBC driver
http://www.ch-werner.de/sqliteodbc/
/usr/local/Cellar/sqliteodbc/0.9995 (11 files, 356.7KB) *
Poured from bottle on 2017-05-22 at 20:52:10
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/sqliteodbc.rb
==> Dependencies
Required: sqlite ✔, unixodbc ✔
配置odbc.ini
与odbcinst.ini
odbc.ini
[PostgreSQL]
Description=PostgreSQL driver for Linux
Driver=/usr/local/Cellar/psqlodbc/09.06.0310/lib/psqlodbcw.so
Setup=/usr/local/Cellar/psqlodbc/09.06.0310/lib/psqlodbcw.so
UsageCount=1
[SQLlite]
Description=ODBC for SQLite
Driver=/usr/local/Cellar/sqliteodbc/0.9995/lib/libsqlite3odbc.so
Setup=/usr/local/Cellar/sqliteodbc/0.9995/lib/libsqlite3odbc.so
UsageCount=5
odbcinst.ini
[Liu]
Description=Liu
Driver=PostgreSQL
Trace=Yes
TraceFile=sql.log
Database=student
Servername=localhost
UserName=root
Password=
Port=5432
Protocol=6.4
ReadOnly=No
RowVersioning=No
ShowSystemTables=No
ShowOidColumn=No
FakeOidIndex=No
[Nian]
Description=Nian
Driver=SQLlite
Trace=Yes
Database=student.db
TraceFile=sql.log
Servername=localhost
Port=1433
ReadOnly=No
RowVersioning=No
ShowSystemTables=No
ShowOidColumn=No
FakeOidIndex=No
这里要注意 SQLite的数据库要选择具体文件
SQLite测试连接
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
int main()
{
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret; /* ODBC API return status */
SQLCHAR outstr[1024];
SQLSMALLINT outstrlen;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
ret = SQLDriverConnect(dbc, NULL, (SQLCHAR*)"DSN=Nian;", SQL_NTS,
outstr, sizeof(outstr), &outstrlen,
SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret))
{
printf("Connected\n");
printf("Returned connection string was:\n\t%s\n", outstr);
if (ret == SQL_SUCCESS_WITH_INFO){
printf("Driver reported the following diagnostics\n");
}
SQLDisconnect(dbc); /* disconnect from driver */
}
else
{
fprintf(stderr, "Failed to connect\n");
}
/* free up allocated handles */
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
}
测试fetch数据
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
int main()
{
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns; /* number of columns in result-set */
SQLSMALLINT rows; /* number of columns in result-set */
int row = 0;
int j = 0,i = 0;
SQLINTEGER indicator;
char buf[512];
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
/* You will need to change mydsn to one you have created and tested */
ret = SQLDriverConnect(dbc, NULL, "DSN=Nian;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)){ printf("Connected\n");}
/* Allocate a statement handle */
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (ret == -1) { printf("fail\n");}
/* Retrieve a list of tables */
SQLTables(stmt, NULL, 0, NULL, 0, NULL, 0, "TABLE", SQL_NTS);
ret = SQLExecDirect(stmt, "select * from student;", SQL_NTS);
printf("return %d\n",ret);
// printf("%d\n",ret);
/* How many columns are there */
SQLNumResultCols(stmt, &columns);
printf("Columns:%d\n",columns);
// /* How many rows are there */
// ret = SQLFetch(stmt);
// ret = SQLRowCount(stmt,&rows);
// printf("%d\n",rows);
/* Loop through the rows in the result-set */
while (SQL_SUCCEEDED(ret = SQLFetch(stmt))){
printf("Row %d\n", row++);
j = 1;
/* Loop through the columns */
while(j <= columns){
i = j;
/* retrieve column data as a string */
ret = SQLGetData(stmt, i, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)){
/* Handle null columns */
if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");
printf("\tColumn %u : %10s len:%d\n",i, buf,indicator);
}
j++;
}
}
}
简单数据库迁移
这里只是最简单的数据库迁移演示,直接用字符串缓冲区进行操作。
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>
char readdata[200][2][30];
int row;
void read_data();
void write_data();
int main(){
read_data();
write_data();
}
void write_data(){
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns; /* number of columns in result-set */
SQLSMALLINT rows; /* number of columns in result-set */
int j = 0,i = 0;
SQLINTEGER indicator;
char buf[512];
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
/* You will need to change mydsn to one you have created and tested */
ret = SQLDriverConnect(dbc, NULL, "DSN=Nian;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)){ printf("Connected\n");}
/* Allocate a statement handle */
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (ret == -1) { printf("fail\n");}
/* Retrieve a list of tables */
printf("row%d\n",row);
for(i = 0; i< row;i++){
printf("Row %d\n",i);
sprintf(buf,"insert into student values(%s,\'%s\');",readdata[i][0],readdata[i][1]);
printf("%s\n",buf);
ret = SQLExecDirect(stmt,buf, SQL_NTS);
if (ret == -1) { printf("fail\n");}
}
}
void read_data(){
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret; /* ODBC API return status */
SQLSMALLINT columns; /* number of columns in result-set */
SQLSMALLINT rows; /* number of columns in result-set */
int j = 0,i = 0;
SQLINTEGER indicator;
char buf[512];
row = 0;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
/* You will need to change mydsn to one you have created and tested */
ret = SQLDriverConnect(dbc, NULL, "DSN=Liu;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (SQL_SUCCEEDED(ret)){ printf("Connected\n");}
/* Allocate a statement handle */
ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (ret == -1) { printf("fail\n");}
/* Retrieve a list of tables */
// SQLTables(stmt, NULL, 0, NULL, 0, NULL, 0, "TABLE", SQL_NTS);
ret = SQLExecDirect(stmt, "select * from student", SQL_NTS);
// printf("%d\n",ret);
/* How many columns are there */
SQLNumResultCols(stmt, &columns);
printf("Columns:%d\n",columns);
// /* How many rows are there */
// ret = SQLFetch(stmt);
// ret = SQLRowCount(stmt,&rows);
// printf("%d\n",rows);
/* Loop through the rows in the result-set */
while (SQL_SUCCEEDED(ret = SQLFetch(stmt))){
printf("Row %d\n", row++);
j = 1;
/* Loop through the columns */
while(j <= columns){
i = j;
/* retrieve column data as a string */
ret = SQLGetData(stmt, i, SQL_C_CHAR, buf, sizeof(buf), &indicator);
if (SQL_SUCCEEDED(ret)){
/* Handle null columns */
if (indicator == SQL_NULL_DATA) strcpy(buf, "NULL");
buf[indicator] = '\0';
strcpy(readdata[row][j-1],buf);
printf("\tColumn %u :%s len:%d\n",i, readdata[row][j-1],indicator);
}
j++;
}
}
}
SQLite
$ sqlite3 student.db
SQLite version 3.16.0 2016-11-04 19:09:39
Enter ".help" for usage hints.
sqlite> select * from student;
1|Liu
0|stu_0
2|stu_2
3|stu_3
4|stu_4
5|stu_5
6|stu_6
7|stu_7
8|stu_8
9|stu_9
...
Makefile
ODBCLIB = /usr/local/Cellar/unixodbc/2.3.4/lib/libodbc.2.dylib /usr/local/Cellar/unixodbc/2.3.4/lib/libodbcinst.2.dylib /usr/local/Cellar/unixodbc/2.3.4/lib/libodbccr.2.dylib
ODBCINC = -I/usr/local/Cellar/unixodbc/2.3.4/include/
all:simple odbc connect fetch update
simple:simple.c
gcc -o simple simple.c $(ODBCLIB) $(ODBCINC)
odbc:odbc.c
gcc -o odbc odbc.c $(ODBCLIB) $(ODBCINC)
connect:connect.c
gcc -o connect connect.c $(ODBCLIB) $(ODBCINC)
connectlite:connectlite.c
gcc -o connectlite connectlite.c $(ODBCLIB) $(ODBCINC)
fetch:fetchresult.c
gcc -o fetch fetchresult.c $(ODBCLIB) $(ODBCINC)
fetchlite:fetchresultlite.c
gcc -o fetchlite fetchresultlite.c $(ODBCLIB) $(ODBCINC)
update:updatedata.c
gcc -o update updatedata.c $(ODBCLIB) $(ODBCINC)
trans:transdata.c
gcc -o trans transdata.c $(ODBCLIB) $(ODBCINC)
clean:
-rm odbc
-rm simple
...
macOS上的ODBC-利用unixODBC连接PostgreSQL与SQLite并进行数据迁移的更多相关文章
- python2/3 利用psycopg2 连接postgreSQL数据库。
psycopg2 是一个通过python连接postgreSQL的库, 不要被它的名称蒙蔽了,你可能发现它的版本是psyconpg2.7.*, 以为它只能在python2上使用,实际上,这只是一个巧合 ...
- 利用Kettle进行SQLServer与Oracle之间的数据迁移实践
Kettle简介 Kettle(网地址为http://kettle.pentaho.org/)是一款国外开源的ETL工具,纯java编写,可以在Windows.Linux.Unix上运行,数据抽取高效 ...
- Entity Framework 6连接Postgresql、SQLite、LocalDB的注意事项和配置文件
Postgresql Postgresql支持Code First的方式自动生成表,不过默认的模式是dbo而不是public,而且还可以自动生成自增主键. <?xml version=" ...
- (一)通过JAVA连接SAP (sapjco3.jar在Windows和MacOS上的配置)
(一)通过JAVA连接SAP调用接口 (sapjco3.jar在Windows和MacOS上的配置) 一.sapjoc3.jar获取 由于sap官网提供的链接需要合作公司提供账号密码,如果商用请索要正 ...
- 在MacOS上利用docker构建buildroot
之前有听说过docker,但是一直没有使用过.最近终于下定决定使用了一下docker,感觉docker用于跨操作系统的软件工具使用还是比较友好的. 适用人群 本文忽略的部分Linux软件包安装的过程, ...
- debian C++ OTL库 用 unixodbc 连接 mysql 小记
这个东东也是折腾了几天,网上很多文章可能已经过时,所以写下不同,以备后用. 参考网址: http://blog.csdn.net/genganpeng/article/details/7402229 ...
- iOS macOS的后渗透利用工具:EggShell
EggShell是一款基于Python编写的iOS和macOS的后渗透利用工具.它有点类似于metasploit,我们可以用它来创建payload建立侦听.此外,在反弹回的session会话也为我们提 ...
- 【戾气满满】Ubuntu 18.04使用QT通过FreeTDS+unixODBC连接MSSQL填坑记(含泪亲测可用)
前言 照例废话几句,想玩下QT,但是学习吧总得想点事情做啊,单纯学习语法用法这些?反正我是学不下去的,脑袋一拍,就先学下怎么连接数据库吧!然而万万没想到,我这是给自己挖了一个深深的坑啊! 学习自然去官 ...
- powerdesigner连接postgresql数据库生成pdm及word文档
1.准备软件: powerdesigner165与postgresql的驱动:psqlodbc_11_01_0000 2.安装并破解完成powerdesigner165 参看链接:https://ww ...
随机推荐
- [补档]暑假集训D4总结
考试 爆零了,不开心,打了两道自己以为是正解的东西,打了两道样例骗分,结果发现并没有给样例分= =,自己以为的正解也打挂了,所以就很= = 但是没办法啊,自己弱也不能怪谁,考试这东西有时候也很玄学. ...
- Dubbo负载均衡策略
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用. 可以自行扩展负载均衡策略,参见:负载均衡扩展Random LoadBalance 随机,按权重设置随机概率. 在一个截面上 ...
- metasploit快速入门
今天没上班,在小黑屋里看了一个一百多页的书<metasploit新手指南>,在此将笔记分享给大家.欢迎大家批评指正,共同学习进步. metasploit新手指南 笔记 kali 0 ...
- ReactiveSwift源码解析(十) Lifetime代码实现
为了之后博客的进行,本篇博客我们就来聊一下ReactiveSwift框架中的Lifetime类的具体实现.从Lifetime这个名字中我们就这道,就是生命周期.在ReactiveSwift中使用Lif ...
- HTML的正确入门姿势——基本结构与基本标签
一.什么是HTML HTML是超文本标签语言,即网页的源码.而浏览器就是翻译解释HTML源码的工具. 二.HTML文档的结构 HTML文档主要包括三大部分:文档声明部分.<head>头部部 ...
- Linux操作系统-命令-aptitude install unzip
如果linux系统没有自带unzip,请执行aptitude install unzip以安装. 使用到这条Linux命令的场景是: 当我把Jmeter的压缩包(xxx.zip)拷贝到远程的Linux ...
- 6个Linux chkconfig命令实例 - 增加,删除,查看和修改services的自动启动选项
注意:service的安装目录在/etc/rc.d/init.d下,/etc/init.d 是/etc/rc.d/init.d的链接. chkconfig命令用来安装,查看或修改 services随系 ...
- 关于java中用itext导出word的一点想法
这几天在项目组只做了很少的事情,主要还是自己不认真地说.我的部分是要负责用itext导出word文档这一块,之前看到大佬们做出了EXCEL部分觉得很是惊奇,就像刚刚接触HTML一样的感觉.但是毕竟自己 ...
- 再学python类(终结篇)
续写 初学python类,这几天吃坏东西了,拖着虚弱的身躯写的.有些乱请各位看官海涵. 声明:本人编程新手,还在学习中.所表述的东西都是基础语法之类的,分享我的学习笔记.还望多多指点,我一定虚心接受. ...
- win10 永久激活 命令行方式
现在我们可以看下当前系统的激活状态,查看方法"WIN+R"打开运行对话框,输入命令slmgr.vbs -xpr,点击确定,这样可以查看到当前系统的激活信息.大家可以发现,虽然小编系 ...