ODBC:如何在執行SQL插入操作時返回主鍵列的自增值和其它列的預設生成值
阿新 • • 發佈:2018-12-21
執行SQL插入操作時,如果能將主鍵列的自增值和其它列的預設生成值一同返回,將極大的提高SQL的執行效率。我們知道,如果是編寫儲存過程的話,是可以解決這個問題的。但編寫儲存過程的問題是需要單獨編寫並在資料庫中建立,如果表比較多的話不太好維護。那是否可以不用儲存過程,只用一條SQL語句就可以解決這個問題呢?下面我們使用MS SQL資料庫和ODBC驅動看怎麼解決這個問題。
假設有如下表:
CREATE TABLE tb_test( id bigint IDENTITY(1,1) PRIMARY KEY, --id,自增主鍵 name varchar(50) NOT NULL, --名字 crt_dtm datetime DEFAULT (sysdatetime()), --建立時間,插入時會賦當前預設時間 opt_dtm datetime NULL, --操作時間 size int NOT NULL --大小 )
其中,id是自增主鍵列,crt_dtm在使用者未輸入時提供當前時間作為預設值。一般會執行的SQL語句如下:
insert into tb_test (name, opt_dtm, size) values (?,?,?)
但這條語句本身不會返回id和crt_dtm的值,所以我們要藉助MS SQL的表變數和output語句將這兩個值取出。
declare @t table (id bigint, crt_dtm datetime); INSERT INTO tb_test(name, opt_dtm, size) OUTPUT INSERTED.id, INSERTED.crt_dtm INTO @t VALUES (?, ?, ?); SELECT id, crt_dtm FROM @t;
首先,建立表變數t,其中定義了id和crt_dtm兩個欄位,用於將insert後生成的值存放到這兩個欄位中;
然後,在insert語句中使用OUTPUT語句,將insert後生成的id和crt_dtm的值儲存到表變數t對應的列中;
最後,查詢表變數t,將id和crt_dtm兩個欄位的值返回。
下面來看看如何使用ODBC來執行此SQL語句:
void execSql(SQLHSTMT hstmt, SQLCHAR* name, SQL_TIMESTAMP_STRUCT optDtm, SQLUINTEGER size) { SQLRETURN retCode; SQLLEN cbSize = 0, cbOptDtm = 0, cbName = SQL_NTS; retCode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, 100, 0, (SQLPOINTER)name, 0, &cbName); retCode = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 30, 0, &optDtm, 0, &cbOptDtm); retCode = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 20, 0, &size, 0, &cbSize); SQLWCHAR* sql = (SQLWCHAR*)L"declare @t table (id bigint, crt_dtm datetime2); INSERT INTO tb_test(name, opt_dtm, size) OUTPUT INSERTED.id, INSERTED.crt_dtm INTO @t VALUES (?, ?, ?); SELECT id, crt_dtm FROM @t;"; retCode = SQLPrepare(hstmt, sql, SQL_NTS); retCode = SQLExecute(hstmt); long id = 0; SQL_TIMESTAMP_STRUCT crtDtm; SQLLEN cbId = 0, cbCrtDtm = 0; retCode = SQLBindCol(hstmt, 1, SQL_C_SLONG, &id, 8, &cbId); retCode = SQLBindCol(hstmt, 2, SQL_C_TYPE_TIMESTAMP, &crtDtm, sizeof(crtDtm), &cbCrtDtm); retCode = SQLMoreResults(hstmt); // (1) retCode = SQLFetch(hstmt); std::stringstream ss; ss << crtDtm.year << "-" << crtDtm.month << "-" << crtDtm.day << " " << crtDtm.hour << ":" << crtDtm.minute << ":" << crtDtm.second << "." << crtDtm.fraction; std::cout << std::to_string(id) << ":" << ss.str() << std::endl; }
此函式執行完成後就可以把最新的id和crtDtm的值取出。
這段程式碼中最關鍵的是(1)這行程式碼,由於sql中包含一個insert和一個select,所以返回結果是兩個結果集,如果要取到select的返回結果集,就需要呼叫SQLMoreResults移動到下一個結果集。
參考文件