(书接上回)
数据库:关于BULK INSERT 学习笔记(1)_wenluderen的专栏-CSDN博客
***
上回完成外围的准备工作, 下面就是准备一个Sql语句,
**
甲:
得到一个语句的句柄,
ret = SQLAllocHandle(SQL_HANDLE_STMT, L_hDbc, &hStmt_yuju);//基于设备句柄 得到语句句柄
**
乙:
ODBC学习笔记—SQLSetStmtAttr_不上进的程序员-CSDN博客
**
ret = SQLSetStmtAttr(hStmt_yuju, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(s_m_g), 0);//
**
SQL_ATTR_ROW_BIND_TYPE---》当 SQLFetch , SQLFetchScroll 被使用时,确定绑定方向.
列方向绑定用 SQL_BIND_BY_COLUMN.
感觉是数据传递的方向。
丙:
ret = SQLSetStmtAttr(hStmt_yuju, SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER)sizeof(s_m_g), SQL_IS_INTEGER);
**
动态参数的绑定方向
SQL_ATTR_PARAM_BIND_TYPE-----》SQL_PARAM_BIND_BY_COLUMN 默认值,以列为方向 。
丁:
ret = SQLSetStmtAttr(hStmt_yuju, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)(long)ROW_ARRAY_SIZE, SQL_IS_INTEGER);
**
SQL_ATTR_PARAMSET_SIZE------------->指定每个参数的取值个数. 数组元素的个数。每个数组元素对应数据库里面一行数据。
**
戊:
定义个一个数组,并且用0初始化
SQLUSMALLINT ParamStatusArray[ROW_ARRAY_SIZE] = { 0 };
(typedef unsigned short SQLUSMALLINT;)
(//#define ROW_ARRAY_SIZE 1000//每次插入的行数)
己:
设定状态数组
ret = SQLSetStmtAttr(hStmt_yuju, SQL_ATTR_ROW_STATUS_PTR, ParamStatusArray, 0);//SQL_ATTR_ROW_STATUS_PTR-->当 SQLFetch 或 SQLFetchScroll时行状态描述数组.
庚:
SQL_ATTR_ROW_BIND_OFFSET_PTR-->替换列绑定指针,非空
SQLINTEGER nBindOffset = 0;//typedef long SQLINTEGER;
ret = SQLSetStmtAttr(hStmt_yuju, SQL_ATTR_ROW_BIND_OFFSET_PTR, (SQLPOINTER)&nBindOffset, 0);
辛:
准备SQL语句
SQLTCHAR sql[] = _T("Insert into ashare_ordwth (rec_num, date, time, reff, acc, stock, bs, price, qty, status, owflag, ordrec, firmid, branchid, checkord) Values(?, ?, ?, ?, ?,?,?, ?, ?, ?, ?, ?, ?, ?, ?)");
//ashare_ordwth 是表的名字
癸:
绑定SQL语句的参数
//参数1:句柄
//参数2:参数序号从1开始
//参数3:入参 出参标识
//参数4:字段的C数据标识符
//参数5:字段的Sql数据标识符
//参数6:数据类型使用的最大位数,或数据的精度
//参数7:如果是浮点是,则对应的字段精度
//参数8:参数值的缓冲区
//参数9:XX
//参数10:XX
SQLBindParameter(hStmt_yuju, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, sizeof(s_m_g_array[0].rec_num), 0, &s_m_g_array[0].rec_num, sizeof(s_m_g_array[0].rec_num), &s_m_g_array[0].rec_numInd);
SQLBindParameter(hStmt_yuju, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].date) - 1, 0, &s_m_g_array[0].date, sizeof(s_m_g_array[0].date), &s_m_g_array[0].dateInd);
SQLBindParameter(hStmt_yuju, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].time) - 1, 0, &s_m_g_array[0].time, sizeof(s_m_g_array[0].time), &s_m_g_array[0].timeInd);
SQLBindParameter(hStmt_yuju, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].reff) - 1, 0, &s_m_g_array[0].reff, sizeof(s_m_g_array[0].reff), &s_m_g_array[0].reffInd);
SQLBindParameter(hStmt_yuju, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].acc) - 1, 0, &s_m_g_array[0].acc, sizeof(s_m_g_array[0].acc), &s_m_g_array[0].accInd);
SQLBindParameter(hStmt_yuju, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].stock) - 1, 0, &s_m_g_array[0].stock, sizeof(s_m_g_array[0].stock), &s_m_g_array[0].stockInd);
SQLBindParameter(hStmt_yuju, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].bs) - 1, 0, &s_m_g_array[0].bs, sizeof(s_m_g_array[0].bs), &s_m_g_array[0].bsInd);
SQLBindParameter(hStmt_yuju, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].price) - 1, 0, &s_m_g_array[0].price, sizeof(s_m_g_array[0].price), &s_m_g_array[0].priceInd);
SQLBindParameter(hStmt_yuju, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].qty) - 1, 0, &s_m_g_array[0].qty, sizeof(s_m_g_array[0].qty), &s_m_g_array[0].qtyInd);
SQLBindParameter(hStmt_yuju, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].status) - 1, 0, &s_m_g_array[0].status, sizeof(s_m_g_array[0].status), &s_m_g_array[0].statusInd);
SQLBindParameter(hStmt_yuju, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].owflag) - 1, 0, &s_m_g_array[0].owflag, sizeof(s_m_g_array[0].owflag), &s_m_g_array[0].owflagInd);
SQLBindParameter(hStmt_yuju, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].ordrec) - 1, 0, &s_m_g_array[0].ordrec, sizeof(s_m_g_array[0].ordrec), &s_m_g_array[0].ordrecInd);
SQLBindParameter(hStmt_yuju, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].firmid) - 1, 0, &s_m_g_array[0].firmid, sizeof(s_m_g_array[0].firmid), &s_m_g_array[0].firmidInd);
SQLBindParameter(hStmt_yuju, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(s_m_g_array[0].branchid) - 1, 0, &s_m_g_array[0].branchid, sizeof(s_m_g_array[0].branchid), &s_m_g_array[0].branchidInd);
SQLBindParameter(hStmt_yuju, 15, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, sizeof(s_m_g_array[0].checkord), 0, &s_m_g_array[0].checkord, sizeof(s_m_g_array[0].checkord), &s_m_g_array[0].checkordInd);
***********************
金:
用法类似于SQLSetEnvAttr,该函数是设置连接的各项属性用的
//参数1: SQLHDBC ConnectionHandle,
//参数2: SQLINTEGER Attribute,
//参数3: SQLPOINTER ValuePtr,
//参数4: SQLINTEGER StringLength
SQLSetConnectAttr(L_hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
//SQL_AUTOCOMMIT_OFF = 驱动程序使用手动提交模式,应用程序必须使用 SQLEndTran 显式提交或回滚事务。
木:
SQLPrepare 准备SQL字符串以执行。 是一种典型的空间换时间的算法优化。
//ODBC中的一个API函数,用来创建SQL语句。
//参数1:StatementHandle SQL语句句柄
//参数2:StatementText SQL语句
//参数3:TextLength SQL字符串长度
ret = SQLPrepare(hStmt_yuju, sql, SQL_NTS);
水:
给卡车装货, 前文说到, BULK INSERT 是把一堆数据整理好,码放整齐,放入卡车,一次性拉入超市。这样速度快。
int rec_num = 1;
for (int i = 0; i < ROW_ARRAY_SIZE; i++)// 给数据赋值
{
s_m_g_array[i].rec_num = rec_num++;
s_m_g_array[i].ordrecInd = 0;
strcpy((char*)s_m_g_array[i].date, "20150120");
s_m_g_array[i].dateInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].time, "13:20:10");
s_m_g_array[i].timeInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].reff, "1234567890");
s_m_g_array[i].reffInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].acc, "0000011111");
s_m_g_array[i].accInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].stock, "123456");
s_m_g_array[i].stockInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].bs, "B");
s_m_g_array[i].bsInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].price, "1.000");
s_m_g_array[i].priceInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].qty, "1000");
s_m_g_array[i].qtyInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].status, "R");
s_m_g_array[i].statusInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].owflag, "ORD");
s_m_g_array[i].owflagInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].ordrec, "1");
s_m_g_array[i].ordrecInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].firmid, "123");
s_m_g_array[i].firmidInd = SQL_NTS;
strcpy((char*)s_m_g_array[i].branchid, "20201");
s_m_g_array[i].branchidInd = SQL_NTS;
::memset(s_m_g_array[i].checkord, 0, sizeof(s_m_g_array[i].checkord));
s_m_g_array[i].checkordInd = sizeof(s_m_g_array[i].checkord);
}
火:
执行语句,并检查错误,如果没有错误就提交
ret = SQLExecute(hStmt_yuju);
if (ret == SQL_ERROR)
{
//wchar_t
// SQLCHAR
//typedef unsigned char SQLCHAR;
SQLWCHAR msg[128];
SQLWCHAR state[128];
SQLINTEGER error_id;
SQLSMALLINT text;
SQLGetDiagRec(SQL_HANDLE_STMT, hStmt_yuju, 1, state, &error_id, msg, 128, &text);
printf("db Insert fail, sqlstate=%s, errormsg=%s\n", state, msg);
SQLEndTran(SQL_HANDLE_DBC, L_hDbc, SQL_ROLLBACK);
system("pause");
return 0;//返回 就不在提交事务,这个程序写很严谨啊
}
else if (ret == SQL_SUCCESS_WITH_INFO)
{
SQLWCHAR msg[128];
SQLWCHAR state[128];
SQLINTEGER error_id;
SQLSMALLINT text;
SQLGetDiagRec(SQL_HANDLE_STMT, hStmt_yuju, 1, state, &error_id, msg, 128, &text);
printf("warning msg=%s\n", msg);
}
//SQLEndTran 针对与连接关联的所有语句的所有活动操作请求提交或回滚操作。
//SQLEndTran 还可以请求对与环境关联的所有连接执行提交或回滚操作。
SQLEndTran(SQL_HANDLE_DBC, L_hDbc, SQL_COMMIT);//SQL_COMMIT--提交事务
printf("写入事物已经提交\n");
土:
释放语句句柄
if (hStmt_yuju)
{
ret = SQLFreeHandle(SQL_HANDLE_STMT, hStmt_yuju);
}