VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

执行SQL语句并处理结果

向数据库发出执行SQL的请求时,需要使用语句句柄,并调用SQLExecDirect或SQLExecute发出查询,服务端执行完成后查询的结果将保存在语句句柄中。

执行查询

直接执行

调用SQLAllocHandle()函数获取句柄,调用SQLExecDirect()函数执行查询。

HSTMT V_OD_hstmt = SQL_NULL_HSTMT; //语句句柄
ret = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
if (!SQL_SUCCEEDED(ret))
{
	printf("failed to allocate stmt handle");
	return;
}
/*执行语句*/
ret = SQLExecDirect(V_OD_hstmt, (SQLCHAR *) "select * from test_stu", SQL_NTS);
/*获取结果*/
ret = SQLFetch(V_OD_hstmt);
if (ret == SQL_NO_DATA)
	return;
if (ret == SQL_SUCCESS)
{
char buf[40];
SQLLEN ind;
/*获取列数据*/
	ret = SQLGetData(V_OD_hstmt, 1, SQL_C_CHAR, buf, sizeof(buf), &ind);
}

预编译方式执行

调用SQLAllocHandle()函数获取句柄,使用SQLPrepare预编译语句,使用SQLBindParameter绑定参数,最后调用SQLExecute执行查询

/*初始化句柄*/
ret = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
if (!SQL_SUCCEEDED(ret))
{
	printf("failed to allocate stmt handle");
	exit(1);
}
/*预编译SQL*/
ret = SQLPrepare(V_OD_hstmt, (SQLCHAR *) "SELECT * FROM test_stu WHERE id = ?", SQL_NTS);
CHECK_STMT_RESULT(ret, "SQLPrepare failed", V_OD_hstmt);
SQLLEN cbParam1 = SQL_NTS;
/*绑定参数*/
ret = SQLBindParameter(V_OD_hstmt, 1, SQL_PARAM_INPUT,
						  SQL_C_SLONG,	/* value type */
						 SQL_INTEGER,		/* param type */
						  20,			/* column size */
						  0,			/* dec digits */
						  "1",		/* param value ptr */
						  0,			/* buffer len */
						  &cbParam1		/* StrLen_or_IndPtr */);
CHECK_STMT_RESULT(ret, "SQLBindParameter failed", V_OD_hstmt);
/*执行*/
ret = SQLExecute(V_OD_hstmt);
CHECK_STMT_RESULT(ret, "SQLExecute failed", V_OD_hstmt);
/*获取结果*/
/*获取结果*/
ret = SQLFetch(V_OD_hstmt);
if (ret == SQL_NO_DATA)
	return;
if (ret == SQL_SUCCESS)
{
char buf[40];
SQLLEN ind;
/*获取列数据*/
	ret = SQLGetData(V_OD_hstmt, 1, SQL_C_CHAR, buf, sizeof(buf), &ind);
}

使用游标获取结果

默认情况下,驱动程序将一次性获取查询的所有结果,当某个查询的结果集很庞大时,一次获取所有结果很不合理,因此ODBC驱动程序提供了一种基于数据库游标的结果集处理方法,只获取少量的行缓存在客户端。通过重新定位游标来获取下一批数据。

游标不能在所有情况下使用。有许多限制会使驱动程序一次性获取整个结果集:

  • 连接不能使用自动提交模式,因为后端会在事务结束时关闭游标,因此在自动提交模式下,事务结束后,在从游标获取数据之前,游标已经被关闭。

  • UseDeclareFetch参数设置为true,默认缓存100行数据,为false时将不会使用游标,直接获取整个结果集。

  • 给定的查询语句必须是单条语句,不能是用分号连接在一起的多个语句。

  • 设置fetch size,且fetch size不能为0.

示例:

int rc;
int i;
/*关闭自动提交*/
rc = SQLSetConnectAttr(V_OD_hdbc, SQL_AUTOCOMMIT, (SQLPOINTER) SQL_AUTOCOMMIT_OFF, 0);
	CHECK_CONN_RESULT(rc, "SQL_AUTOCOMMIT off failed", V_OD_hdbc);
/*执行SQL*/
rc = SQLExecDirect(V_OD_hstmt, (SQLCHAR *) "SELECT 'foo' || g FROM generate_series(1, 3210) g", SQL_NTS);
CHECK_STMT_RESULT(rc, "SQLExecDirect failed", V_OD_hstmt);
/*获取结果*/
for (;; i++)
{
char buf[40];
	SQLLEN ind;
	rc = SQLFetch(V_OD_hstmt);
	if (rc == SQL_NO_DATA)
		break;
	if (rc != SQL_SUCCESS)
	{
		char sqlstate[32] = "";
		SQLINTEGER nativeerror;
		SQLSMALLINT textlen;
		SQLGetDiagRec(SQL_HANDLE_STMT, V_OD_hstmt, 1, sqlstate, &nativeerror,
						  NULL, 0, &textlen);
               /*在读取游标的过程中,如果调用用SQLEndTran提交或回滚了事务,游标将被关闭*/
		if (strcmp(sqlstate, "HY010") == 0)
		{
			printf("SQLFetch failed with HY010 (which probably means that the cursor was closed at commit/rollback)");
			break;
		}
		else
			CHECK_STMT_RESULT(rc, "SQLGetDiagRec failed", V_OD_hstmt);
	}

	rc = SQLGetData(V_OD_hstmt, 1, SQL_C_CHAR, buf, sizeof(buf), &ind);
	CHECK_STMT_RESULT(rc, "SQLGetData failed", V_OD_hstmt);
}

执行更新

要更改数据(执行一个insert,update或者delete),可以使用SQLExecDirect函数执行完整的SQL,也可以使用预编译的方式绑定参数后再执行。下面的示例将以预编译的方式执行。

删除

rc = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
rc = SQLPrepare(V_OD_hstmt, (SQLCHAR *) "delete from test_stu where id= ? ", SQL_NTS);
cbParam1 = SQL_NTS;
rc = SQLBindParameter(V_OD_hstmt, 1, SQL_PARAM_INPUT,
SQL_C_SLONG,	/* value type */
SQL_INTEGER,	/* param type */
20,		/* column size */
0,		/* dec digits */
“1”,		/* param value ptr */
0,		/* buffer len */
&cbParam1	/* StrLen_or_IndPtr */);
CHECK_STMT_RESULT(rc, "SQLBindParameter failed", V_OD_hstmt);
rc = SQLExecute(V_OD_hstmt);
CHECK_STMT_RESULT(rc, "SQLExecute failed", V_OD_hstmt);

更新

rc = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
rc = SQLPrepare(V_OD_hstmt, (SQLCHAR *) "update stu_id set name = ‘Lisa’ where id = ? ", SQL_NTS);
cbParam1 = SQL_NTS;
rc = SQLBindParameter(V_OD_hstmt, 1, SQL_PARAM_INPUT,
					SQL_C_SLONG,	/* value type */
					SQL_INTEGER,	/* param type */
					20,		/* column size */
				        0,		/* dec digits */
					“100”,		/* param value ptr */
					0,		/* buffer len */
					&cbParam1	/* StrLen_or_IndPtr */);
CHECK_STMT_RESULT(rc, "SQLBindParameter failed", V_OD_hstmt);
rc = SQLExecute(V_OD_hstmt);
CHECK_STMT_RESULT(rc, "SQLExecute failed", V_OD_hstmt);

插入

rc = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
rc = SQLPrepare(V_OD_hstmt, (SQLCHAR *) "INSERT INTO test_stu VALUES (2, ?) ", SQL_NTS);
cbParam1 = SQL_NTS;
rc = SQLBindParameter(V_OD_hstmt, 1, SQL_PARAM_INPUT,
					SQL_C_CHAR,	/* value type */
					SQL_CHAR,	/* param type */
					20,		/* column size */
					0,		/* dec digits */
					“Jennifer”,		/* param value ptr */
					0,		/* buffer len */
					&cbParam1	/* StrLen_or_IndPtr */);
CHECK_STMT_RESULT(rc, "SQLBindParameter failed", V_OD_hstmt);
rc = SQLExecute(V_OD_hstmt);
CHECK_STMT_RESULT(rc, "SQLExecute failed", V_OD_hstmt);

创建或修改数据库对象

要创建、更改或者删除一个类似表或者视图这样的数据库对象, 可以调用 SQLExecDirect() 方法.

例如创建表:

HSTMT V_OD_hstmt = SQL_NULL_HSTMT; //语句句柄
ret = SQLAllocHandle(SQL_HANDLE_STMT, V_OD_hdbc, &V_OD_hstmt);
if (!SQL_SUCCEEDED(ret))
{
	printf("failed to allocate stmt handle");
	return;
}
ret = SQLExecDirect(V_OD_hstmt, (SQLCHAR *) "create table test(c1 int,c2 int)", SQL_NTS);