volatile MQTTClient_deliveryToken deliveredtoken;

void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}

int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
wstring str = getAppPath();
CDllHelper dllMqtt;
DWORD dwRet = dllMqtt.addDllSearchPath(str + L"ini");
dwRet = dllMqtt.loadDll(str + L"ini/paho-mqtt3c.dll");
if (dwRet)
{
ASSERT(FALSE);
}
auto pMQTTClient_freeMessage = dllMqtt.getDllFunc<void(MQTTClient_message** message)>("MQTTClient_freeMessage");
// m_pMQTTClient_freeMessage = dllMqtt.getDllFunc<void(MQTTClient_message** message)>("MQTTClient_freeMessage");
auto pMQTTClient_free = dllMqtt.getDllFunc<void(void* memory)>("MQTTClient_free");

int i;
char* payloadptr;

printf("Message arrived\n");
printf(" topic: %s\n", topicName);
printf(" message: ");

payloadptr = (char *)message->payload;
for (i = 0; i < message->payloadlen; i++)
{
putchar(*payloadptr++);
}
putchar('\n');
pMQTTClient_freeMessage(&message);
pMQTTClient_free(topicName);
return 1;
}

void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}

wstring str = getAppPath();
CDllHelper dllMqtt;
DWORD dwRet = dllMqtt.addDllSearchPath(str + L"ini");
dwRet = dllMqtt.loadDll(str + L"ini/paho-mqtt3c.dll");
if (dwRet)
{
ASSERT(FALSE);
}
auto pMQTTClient_create = dllMqtt.getDllFunc<int(MQTTClient*, const char*, const char*,int , void*)>("MQTTClient_create");
auto pMQTTClient_connect = dllMqtt.getDllFunc<int(MQTTClient, MQTTClient_connectOptions*)>("MQTTClient_connect");
auto pMQTTClient_destroy = dllMqtt.getDllFunc<void(MQTTClient*)>("MQTTClient_destroy");
auto pMQTTClient_disconnect = dllMqtt.getDllFunc<int(MQTTClient, int)>("MQTTClient_disconnect");
auto pMQTTClient_setCallbacks = dllMqtt.getDllFunc<int(MQTTClient handle, void* context, MQTTClient_connectionLost* cl,
MQTTClient_messageArrived* ma, MQTTClient_deliveryComplete* dc)>("MQTTClient_setCallbacks");
auto pMQTTClient_subscribe = dllMqtt.getDllFunc<int(MQTTClient handle, const char* topic, int qos)>("MQTTClient_subscribe");
auto pMQTTClient_unsubscribe = dllMqtt.getDllFunc<int(MQTTClient handle, const char* topic)>("MQTTClient_unsubscribe");


#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "66889710-BA34-4BBC-811A-ABFC2AD281EB"
#define TOPIC "event/#"
#define PAYLOAD "Hello World!"
#define QOS 1
#define TIMEOUT 10000L

// subscribe
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;

int iRet = pMQTTClient_create(&client, ADDRESS, CLIENTID,MQTTCLIENT_PERSISTENCE_NONE, NULL);
if (MQTTCLIENT_SUCCESS != iRet)
{
ASSERT(FALSE);
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.connectTimeout = 2;
conn_opts.username = "admin";
conn_opts.password = "123456";
conn_opts.MQTTVersion = MQTTVERSION_DEFAULT;

iRet = pMQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered);
if (MQTTCLIENT_SUCCESS != iRet)
{
ASSERT(FALSE);
}
iRet = pMQTTClient_connect(client, &conn_opts);
if (iRet != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", iRet);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
iRet = pMQTTClient_subscribe(client, TOPIC, QOS);
if (MQTTCLIENT_SUCCESS != iRet)
{
ASSERT(FALSE);
}

do
{
ch = getchar();
} while (ch != 'Q' && ch != 'q');

pMQTTClient_unsubscribe(client, TOPIC);
pMQTTClient_disconnect(client, 10000);
pMQTTClient_destroy(&client);

注意事项

  1. not support UTF8 sql string
  2. Access 2016版本之前不支持bitint

https://support.office.com/zh-cn/article/%E4%BD%BF%E7%94%A8%E5%A4%A7%E6%95%B0%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B-5b623f6e-641d-4e97-8bdf-b77bae076f70

大数数据类型可存储非货币的数值,并与 ODBC 中的 SQL_BIGINT 数据类型兼容。请使用这种数据类型以高效计算大数。

大数数据类型的范围
可将大数作为字段添加到 Access 表中。还可通过相应的数据类型(如 SQL Server bigint 数据类型)链接到数据库或从数据库导入。若要添加大数数据类型,需要 Access 2016(16.0.7812 或更高版本)。

where 条件

如果想筛选Access数据表中 Null 和 “” 空字符串 以及 “ “ 空格的数据,则可以使用 trim(nz(字段名))=””

报错: 用户 ‘admin’ 以独占方式的锁定数据表

还没找到好的处理方法.暂时捕获异常,延迟,然后重新执行.

skip_retry:
TRY{
// some sql process
}CATCH(CDBException, e) {
char buf[1024] = { '\0' };
e->GetErrorMessage(&buf[0], 1024);
if (nullptr != strstr(buf, "独占方式"))
{
Sleep(500);
goto skip_retry;
}
ASSERT(FALSE);
if (g_bWriteLog)
{
string strLog = "1biao6shi: manForce Database error: " + e->m_strError;
OutputDebugString(strLog.c_str());
if (g_logger)
{
g_logger->error(strLog);
}
}
}
END_CATCH;

PHP 数据对象PDO扩展为PHP访问数据库定义了一个轻量级的一致接口。PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。

connect

try{
$db = new PDO('sqlite:/var/www/php56/db/pduService.db', null,null,
array(PDO::ATTR_PERSISTENT => true));

$sql = "
INSERT INTO t_demo
(name, age)
VALUES
(:name,:age);
";
$handler->debug($sql, 'db');
try {
// $db->exec("INSERT INTO t_demo(name, age) VALUES('Audi', 52642)") or die(print_r($db->errorInfo(), true));

$stmt = $db->prepare($sql);
$name = 'Tom';
$age = 32;
// Bind parameters to statement variables, 两种方法都可以
// $stmt->bindParam(1, $name);
// $stmt->bindParam(2, $age);
$stmt->bindValue(':name', 'Tom', SQLITE3_TEXT);
$stmt->bindValue(':age', 34, SQLITE3_INTEGER);

$bRet = $stmt->execute();
if ($bRet == false)
{
$handler->debug($db->errorInfo(),"db error");
}else{
$handler->debug("execute sql success","db success");
}
$handler->debug($stmt->rowCount(), 'db rowCount');
$handler->debug($db->lastInsertId(),"db lastInsertId");
} catch (PDOException $e) {
$handler->debug($e->getMessage(), 'db exception');
exit($e->getMessage());
}
$result = $db->query("SELECT * FROM t_demo") or die("query failed.");
var_dump($result->fetchAll());
}catch (PDOException $e)
{
echo $e->getMessage();
}

创建/打开数据库

sqlite3 DatabaseName.db

查询表

命令行输入

.tables
select * from t_account;

查看表DDL语句

.schema

退出

.exit

导入 sql 文件

/usr/sbin/sqlite3 /usr/app/dat.db < /usr/app/1.sql

又是一本看完之后,晕晕乎乎的书。不知道为什么畅销。也在里面学到了一些东西,但是很少。

20190517_070148.png

Illegal mix of collations MySQL Error

// 查看哪个表的字符集有问题
SELECT table_schema, table_name, column_name, character_set_name, collation_name
FROM information_schema.columns
WHERE collation_name = 'utf8mb4_general_ci'
ORDER BY table_schema, table_name,ordinal_position;

// 修改为想要的字符集
ALTER TABLE email CONVERT TO CHARACTER SET utf8mb4 COLLATE 'utf8mb4_unicode_ci';

编码注意

搜索中文

目前可用的是在连接数据库的时候指定编码 dbString = “ODBC;DSN=cxDMSmainMySQL;Trusted_Connection=Yes;CharSet=gbk;”;
使用 gbk 就可以正常了

当编码设为 utf8mb4 的时候,发现无法搜索到中文字段.
使用这个限定符 binary ucase. 之后,搜索的是全部数据,仍然不可用.
ucase 是忽略大小写.

sql = str::cstr::format("SELECT f_plate,f_plate_type,f_car_type,f_name,f_phone_1 FROM t_person_car_info,t_person_info WHERE \
(t_person_info.f_identification_number = t_person_car_info.f_identification_no) and\
(t_person_car_info.f_plate like binary ucase('%s'))", param.c_str());

查看字符集

show variables like '%char%';

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
20190528_151006.png

连接登录设置字符集

mysql --default-character-set=字符集-u root -p 

设置字符集

这里的设置,只是当前有效,重启数据库后,会恢复默认的.

character_set_system:系统字符集,这个值总是utf8,不需要设置。这个字符集用于数据库对象(如表和列)的名字,也用于存储在目录表中的函数的名字。
collation_connection: 当前连接的字符集。

可以通过修改 my.ini 来设置默认字符集

[client]
default-character-set=utf8mb4
// 影响参数
character_set_client
character_set_connection
character_set_results

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
//影响参数:
character_set_database
character_set_server
SET names utf8mb4 COLLATE utf8mb4_unicode_ci;

set character_set_database=utf8mb4;
set character_set_server=utf8mb4;

set collation_server=utf8mb4_unicode_ci;
set collation_database=utf8mb4_unicode_ci;
set collation_connection=utf8mb4_unicode_ci;
SET names utf8 COLLATE utf8_unicode_ci;

set character_set_database=utf8;
set character_set_server=utf8;

set collation_server=utf8_unicode_ci;
set collation_database=utf8_unicode_ci;
set collation_connection=utf8_unicode_ci;

设置字节序 collation

字符序确定在同一字符集内字符之间的比较规则

查看当前字节序

show variables like '%colla%';

查看安装的字符序

show collation;

查看安装的字符集

show character set;

字节序的选择

结论就是使用 utf8mb4_unicode_ci.

字符除了需要存储,还需要排序或比较大小,涉及到与编码字符集对应的 排序字符集(collation)。ut8mb4对应的排序字符集常用的有 utf8mb4_unicode_ci, utf8mb4_general_ci

主要从排序准确性和性能两方面看:

  • 准确性
    utf8mb4_unicode_ci 是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序
    utf8mb4_general_ci 没有实现Unicode排序规则,在遇到某些特殊语言或字符是,排序结果可能不是所期望的。
    但是在绝大多数情况下,这种特殊字符的顺序一定要那么精确吗。比如Unicode把ß、Œ当成ss和OE来看;而general会把它们当成s、e,再如ÀÁÅåāă各自都与 A 相等。

  • 性能
    utf8mb4_general_ci 在比较和排序的时候更快
    utf8mb4_unicode_ci 在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
    但是在绝大多数情况下,不会发生此类复杂比较。general理论上比Unicode可能快些,但相比现在的CPU来说,它远远不足以成为考虑性能的因素,索引涉及、SQL设计才是。 我个人推荐是 utf8mb4_unicode_ci,将来 8.0 里也极有可能使用变为默认的规则。相比选择哪一种collation,使用者应该更关心字符集与排序规则在db里要统一就好。

数据库配置文件

[client]
default-character-set=utf8mb4

[mysqld]
default-character-set=utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
skip-character-set-client-handshake = true

[mysql]
default-character-set = utf8mb4

@@ MySQL数据库中字符集转换流程
MySQL收到请求时将请求数据从character_set_client转换为character_set_connection
进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下
使用每个数据字段的CHARACTER SET设定值
若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准)
若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值
若上述值不存在,则使用character_set_server设定值
将操作结果从内部操作字符集转换为character_set_connection
将响应数据从character_set_connection转为character_set_client
执行SQL语句时信息的路径是这样的

信息输入路径:client → connection → server;

信息输出路径:server → connection → results.

add source by code

SQLCreateDataSource displays a dialog box with which the user can add a data source.

SQLCreateDataSource 

连接字符串

ODBC

MySQL

strConnect = _T("Driver={MySQL ODBC 3.51 Driver};Server=localhost;"
"Database=MyDatabase;User=MyUserName;Password=MyPassword;Option=4;useUnicode=true&characterEncoding=UTF-8");
A:使用ODBC方式

1:dBASE连接字符串
strConnection = _T("Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;"
"Dbq=c:\\DatabasePath;");


2:Excel连接字符串


strConnection = _T("Driver={Microsoft Excel Driver (*.xls)};DriverId=790;"
bq=C:\\DatabasePath\\DBSpreadSheet.xls;DefaultDir=c:\\databasepath;");


3:Text连接字符串


strConnection = _T("Driver={Microsoft Text Driver (*.txt; *.csv)};"
"Dbq=C:\\DatabasePath\\;Extensions=asc,csv,tab,txt;");

4:Visual FoxPro连接字符串

strConnection = _T("Driver={Microsoft Visual Foxpro Driver};UID=;"
urceType=DBC;SourceDB=C:\\DatabasePath\\MyDatabase.dbc;Exclusive=No");

strConnection = _T("Driver={Microsoft Visual Foxpro Driver};UID=;"
"SourceType=DBF;SourceDB=C:\\DatabasePath\\MyDatabase.dbc;Exclusive=No");


5:Access连接字符串


strConnection = _T("Driver={Microsoft Access Driver (*.mdb)};"
"Dbq=c:\\DatabasePath\\dbaccess.mdb;Uid=;Pwd=;");



6::SQL Server连接字符串

strConnection = _T("Driver={SQL Server};Server=MyServerName;"
"Trusted_Connection=no;"
"Database=MyDatabaseName;Uid=MyUserName;Pwd=MyPassword;");

7:Oracle连接字符串

strConnect = _T("Driver={Microsoft ODBC for Oracle};Server=OracleServer.world;"
"Uid=MyUsername;Pwd=MyPassword;");



9:SyBase连接字符串
strConnect = _T("Driver={Sybase System 10};Srvr=MyServerName;Uid=MyUsername;"
"Pwd=myPassword;");

10:SqlAnyWhere连接字符串
strConnect = _T("ODBC;Driver=Sybase SQL Anywhere 5.0;"
"DefaultDir=C:\\DatabasePath\;Dbf=C:\\SqlAnyWhere50\\MyDatabase.db;"
"Uid=MyUsername;Pwd=MyPassword;Dsn=\"\";");


B:使用OLE方式

1:SQL Server连接字符串
标准的:strConnect = _T("Provider=sqloledb;Data Source=MyServerName;"
"Initial Catalog=MyDatabaseName;"
"User Id=MyUsername;Password=MyPassword;");


2:MySQL 连接字符串
strConnection = _T("Provider=MySQLProv;Data Source=test");

3:AS400连接字符串
strConnect = _T("Provider=IBMDA400;Data source=myAS400;User Id=myUsername;"
"Password=myPassword;");

4:DB2连接字符串
使用TCPID
strConnect = _T("Provider=DB2OLEDB;Network Transport Library=TCPIP;"
"Network Address=130.120.110.001;"
"Initial Catalog=MyCatalog;Package Collection=MyPackageCollection;"
"Default Schema=MySchema;User ID=MyUsername;Password=MyPassword;");
使用APPC
strConnect = _T("Provider=DB2OLEDB;APPC Local LU Alias=MyLocalLUAlias;"
"APPC Remote LU Alias=MyRemoteLUAlias;Initial Catalog=MyCatalog;"
"Package Collection=MyPackageCollection;Default Schema=MySchema;"
"User ID=MyUsername;Password=MyPassword;");


5:Microsoft Jet连接字符串
标准的:strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0;"
"Data Source=C:\\DatabasePath\\MmDatabase.mdb;"
"User Id=admin;Password=;");

6:使用OLE连接某一个Excel表
strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0;"
"Data Source=C:\\DatabasePath\\DBSpreadSheet.xls;"
"Extended Properties=\"\"Excel 8.0;HDR=Yes;\"\";");

注意 HDR=Yes 是第一行是字段,会自动过滤

7:OLAP连接字符串
strConnect = _T("Provider=MSOLAP;Data Source=MyOLAPServerName;"
"Initial Catalog=MyOLAPDatabaseName;");

8:Oracle连接字符串

trConnect = _T("Provider=MSDAORA;Data Source=MyOracleDB;User Id=myUsername;"
"Password=myPassword;");

8:Data Link Connections字符串

strConnection = _T("File Name=c:\\DataBasePath\\DatabaseName.udl;");

Q&A

无法解析的外部符号 __imp___vsnprintf

在 vs2015 工程选项,链接器附加依赖项里面添加 legacy_stdio_definitions.lib 即可。
出现这个问题的原因是 vs2015 默认编译时将许多标准库采用内联方式处理,因而没有可以链接的标准库文件,所以要专门添加标准库文件来链接标准库中的函数。