91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL C API執行SQL語句的一種方式

發布時間:2020-04-23 14:59:28 來源:億速云 閱讀:687 作者:三月 欄目:MySQL數據庫

本文主要給大家介紹MySQL C API執行SQL語句的一種方式,其所涉及的東西,從理論知識來獲悉,有很多書籍、文獻可供大家參考,從現實意義角度出發,億速云累計多年的實踐經驗可分享給大家。 

接著看
預處理語句(Prepared Statements)
MySQL C API還提供了另一種方式來執行SQL語句,即先預處理(prepare)再執行
(execute). 對于多次執行的SQL語句,該方式可以提高其執行效率。具體步驟如下:

  1. 調用mysql_stmt_init()創建語句句柄,該句柄在隨后的函數調用中都要用到。
    MYSQL_STMT mysql_stmt_init(MYSQL mysql)

MYSQL_STMT mysql_stmt_init(MYSQL mysql)

描述
創建MYSQL_STMT句柄。對于該句柄,應使用mysql_stmt_close(MYSQL_STMT *)釋放。

返回值
成功時,返回指向MYSQL_STMT結構的指針。如果內存溢出,返回NULL。
錯誤
·         CR_OUT_OF_MEMORY

內存溢出。

MySQL C API執行SQL語句的一種方式

  1. 調用mysql_stmt_prepare()對SQL語句進行預處理
    int mysql_stmt_prepare(MYSQL_STMT stmt, const char stmt_str, unsigned long length)

    int mysql_stmt_prepare(MYSQL_STMT stmt, const char query, unsigned long length)
    描述
    給定mysql_stmt_init()返回的語句句柄,準備字符串查詢指向的SQL語句,并返回狀態值。字符串長度應由“length”參量給出。字符串必須包含1條SQL語句。不應為語句添加終結用分號(‘;’)或\g。
    通過將問號字符“?”嵌入到SQL字符串的恰當位置,應用程序可包含SQL語句中的一個或多個參數標記符。

標記符僅在SQL語句中的特定位置時才是合法的。例如,它可以在INSERT語句的VALUES()列表中(為行指定列值),或與WHERE子句中某列的比較部分(用以指定比較值)。但是,對于ID(例如表名或列名),不允許使用它們,不允許指定二進制操作符(如等于號“=”)的操作數。后一個限制是有必要的,原因在于,無法確定參數類型。一般而言,參數僅在DML(數據操作語言)語句中才是合法的,在DDL(數據定義語言)語句中不合法。

執行語句之前,必須使用mysql_stmt_bind_param(),將參數標記符與應用程序變量綁定在一起。

返回值

如果成功處理了語句,返回0。如果出現錯誤,返回非0值。

  1. 如果SQL語句中有參數,則需要調用mysql_stmt_bind_param()進行參數綁定。
    my_bool mysql_stmt_bind_param(MYSQL_STMT stmt, MYSQL_BIND bind)
    如果參數的類型為TEXT或BLOB, 并且數據量很大,可以調用
    mysql_stmt_send_long_data()來向云服務器發送數據。
    my_bool mysql_stmt_send_long_data(MYSQL_STMT stmt, unsigned int parameter_number, const char data, unsigned long length)

my_bool mysql_stmt_bind_param(MYSQL_STMT stmt, MYSQL_BIND bind)
描述
mysql_stmt_bind_param()用于為SQL語句中的參數標記符綁定數據,以傳遞給mysql_stmt_prepare()。它使用MYSQL_BIND結構來提供數據。“bind”是MYSQL_BIND結構的某一數組的地址。按照客戶端庫的預期,對于查詢中出現的每個“?”參數標記符,數組中均包含1個元素。

假定你準備了下述語句:

INSERT INTO mytbl VALUES(?,?,?)
綁定參數時,MYSQL_BIND結構的數組包含3個元素,并能聲明如下:

MYSQL_BIND bind[3];

返回值

如果綁定成功,返回0。如果出現錯誤,返回非0值。

  1. 調用mysql_stmt_execute()來執行查詢。
    int mysql_stmt_execute(MYSQL_STMT *stmt)

int mysql_stmt_execute(MYSQL_STMT *stmt)

描述

mysql_stmt_execute()執行與語句句柄相關的預處理查詢。在該調用期間,將當前綁定的參數標記符的值發送到服務器,服務器用新提供的數據替換標記符。

如果語句是UPDATE、DELETE或INSERT,通過調用mysql_stmt_affected_rows(),可發現更改、刪除或插入的總行數。如果這是諸如SELECT等能生成結果集的語句,調用任何其他能導致查詢處理的函數之前,必須調用mysql_stmt_fetch()來獲取數據。

對于生成結果集的語句,執行語句之前,可通過調用mysql_stmt_attr_set(),請求mysql_stmt_execute()為語句打開光標。如果多次執行某一語句,在打開新的光標前,mysql_stmt_execute()將關閉任何已打開的光標。

返回值

如果執行成功,返回0。如果出現錯誤,返回非0值。

  1. 若查詢不產生結果集,可以調用
    mysql_stmt_affected_rows()和
    my_ulonglong mysql_stmt_insert_id(MYSQL_STMT stmt)來獲得被改變的記錄數和生成的自增值。
    my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT
    stmt)
    my_ulonglong mysql_stmt_insert_id(MYSQL_STMT stmt)
    否則,執行mysql_stmt_bind_result()對結果集中的字段進行綁定。
    my_bool mysql_stmt_bind_result(MYSQL_STMT
    stmt, MYSQL_BIND *bind)

my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)

描述

返回上次執行語句更改、刪除或插入的總行數。對于UPDATE、DELETE或INSERT語句,可在mysql_stmt_execute()之后立刻調用它們。對于SELECT語句,mysql_stmt_affected_rows()的工作方式類似于mysql_num_rows()。

返回值

大于0的整數指明了受影響或檢索的行數。對于UPDATE語句,“0”表明未更新任何記錄,在查詢中沒有與WHERE子句匹配的行,或尚未執行任何查詢。“-1”表明返回了錯誤,或對SELECT查詢,在調用mysql_stmt_store_result()之前調用了mysql_stmt_affected_rows()。由于mysql_stmt_affected_rows()返回無符號值,可通過比較返回值和“(my_ulonglong)-1”(或等效的“(my_ulonglong)~0”),檢查“-1”。

  1. 調用mysql_stmt_fetch()來逐行獲取結果集中的記錄。
    int mysql_stmt_fetch(MYSQL_STMT stmt)
    在調用mysql_stmt_fetch()之前,還可以執行mysql_stmt_store_result()將結果
    集預先緩存到本地。
    int mysql_stmt_store_result(MYSQL_STMT
    stmt)

int mysql_stmt_store_result(MYSQL_STMT *stmt)

描述

對于成功生成結果集的所有語句(SELECT、SHOW、DESCRIBE、EXPLAIN),而且僅當你打算對客戶端的全部結果集進行緩沖處理時,必須調用mysql_stmt_store_result(),以便后續的mysql_stmt_fetch()調用能返回緩沖數據。

對于其他語句,沒有必要調用mysql_stmt_store_result(),但如果調用了它,也不會造成任何傷害或導致任何性能問題。通過檢查mysql_stmt_result_metadata()是否返回NULL,可檢測語句是否生成了結果集。
返回值

如果成功完成了對結果的緩沖處理,返回0。如果出現錯誤,返回非0值。

  1. 重復步驟3-6, 每次使用不同的實參來執行查詢。
  2. 調用mysql_stmt_close()關閉句柄,釋放資源
    my_bool mysql_stmt_close(MYSQL_STMT )
    此外,可以調用mysql_stmt_errno()和mysql_stmt_error()來獲知最近執行的預處
    理語句API函數的錯誤代碼和錯誤信息。
    unsigned int mysql_stmt_errno(MYSQL_STMT
    stmt)
    const char mysql_stmt_error(MYSQL_STMT stmt)

總體而言:

MySQL客戶端/服務器協議提供了預處理語句。該功能采用了由mysql_stmt_init()初始化函數返回的MYSQL_STMT語句處理程序數據結構。對于多次執行的語句,預處理執行是一種有效的方式。首先對語句進行解析,為執行作好準備。接下來,在以后使用初始化函數返回的語句句柄執行一次或多次。
對于多次執行的語句,預處理執行比直接執行快,主要原因在于,僅對查詢執行一次解析操作。在直接執行的情況下,每次執行語句時,均將進行查詢。此外,由于每次執行預處理語句時僅需發送參數的數據,從而減少了網絡通信量。
預處理語句的另一個優點是,它采用了二進制協議,從而使得客戶端和服務器之間的數據傳輸更有效率。
編程步驟
?1.  用mysql_stmt_init()創建預處理語句句柄。要想在服務器上準備預處理語句,可調用mysql_stmt_prepare(),并為其傳遞包含SQL語句的字符串
?2.  如果語句生成了結果集,調用mysql_stmt_result_metadata()以獲得結果集元數據。雖然與包含查詢返回列的結果集不同,該元數據本身也采用了結果集的形式。元數據結果集指明了結果中包含多少列,并包含每一列的信息。
?3.  使用mysql_stmt_bind_param()設置任何參數的值。必須設置所有參數。否則,語句執行將返回錯誤,或生成無法預料的結果。
?4.  調用mysql_stmt_execute()執行語句。
?5.  如果語句生成了結果集,捆綁數據緩沖,通過調用mysql_stmt_bind_result(),檢索行值。
?6.  通過重復調用mysql_stmt_fetch(),按行將數據提取到緩沖區,直至未發現更多行為止。
?7.  通過更改參數值并再次執行語句,重復步驟3到步驟6。

實現代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

#define STRING_SIZE 50

#define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
#define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\
col2 VARCHAR(40),\
col3 SMALLINT,\
col4 TIMESTAMP)"
#define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"

//int main(char *argv, int argc)
int main(char
argv[], int argc)
{
int     ret = 0, i = 0;

MYSQL   *mysql;
MYSQL   *connect = NULL;
char    sqlbuf[2048];

mysql = mysql_init(NULL) ;  
if (mysql == NULL)
{
    ret =  mysql_errno(&mysql) ;
    printf("func mysql_init() err \n");
    return ret;
}
printf("func mysql_init() ok \n");

connect = mysql_real_connect(mysql, "localhost", "root", "123456", "mydb2", 0, NULL, 0);
if (connect == NULL)
{
    ret =  mysql_errno(&mysql) ;
    printf("func mysql_init() err \n");
    return ret; 
}
printf("func mysql_real_connect() ok \n");

MYSQL_STMT    *stmt;
MYSQL_BIND    bind[3];
my_ulonglong  affected_rows;
int           param_count;
short         small_data;
int           int_data;
char          str_data[STRING_SIZE];
unsigned long str_length;
my_bool       is_null;

if (mysql_query(mysql, DROP_SAMPLE_TABLE))
{
  fprintf(stderr, " DROP TABLE failed\n");
  fprintf(stderr, " %s\n", mysql_error(mysql));
  exit(0);
}

if (mysql_query(mysql, CREATE_SAMPLE_TABLE))
{
  fprintf(stderr, " CREATE TABLE failed\n");
  fprintf(stderr, " %s\n", mysql_error(mysql));
  exit(0);
}

/* Prepare an INSERT query with 3 parameters */
/* (the TIMESTAMP column is not named; the server */
/*  sets it to the current date and time) */
stmt = mysql_stmt_init(mysql);  //初始化預處理環境句柄  MYSQL_STMT *stmt
if (!stmt)
{
  fprintf(stderr, " mysql_stmt_init(), out of memory\n");
  exit(0);
}
if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE)))  //向預處理環境句柄stmt 中添加sql( 帶有占位符)
{
  fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}
fprintf(stdout, " prepare, INSERT successful\n");

/* Get the parameter count from the statement */
param_count= mysql_stmt_param_count(stmt);   //獲取sql語言中 占位符 的個數
fprintf(stdout, " total parameters in INSERT: %d\n", param_count);

if (param_count != 3) /* validate parameter count */
{
  fprintf(stderr, " invalid parameter count returned by MySQL\n");
  exit(0);
}

/* Bind the data for all 3 parameters */

memset(bind, 0, sizeof(bind));

/* INTEGER PARAM */
/* This is a number type, so there is no need to specify buffer_length */
bind[0].buffer_type= MYSQL_TYPE_LONG;  //設置第一個占位符的屬性
bind[0].buffer= (char *)&int_data;
bind[0].is_null= 0;
bind[0].length= 0;

/* STRING PARAM */
bind[1].buffer_type= MYSQL_TYPE_STRING; //設置第2個占位符的屬性
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= STRING_SIZE;
bind[1].is_null= 0;
bind[1].length= &str_length;

/* SMALLINT PARAM */
bind[2].buffer_type= MYSQL_TYPE_SHORT; //設置第3個占位符的屬性
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null;
bind[2].length= 0;

/* Bind the buffers */
if (mysql_stmt_bind_param(stmt, bind))  //把設置好的屬性 加入預處理環境stmt中
{
  fprintf(stderr, " mysql_stmt_bind_param() failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

/* Specify the data values for the first row */    //準備插入數據
int_data= 10;             /* integer */
strncpy(str_data, "MySQL", STRING_SIZE); /* string  */
str_length= strlen(str_data);

/* INSERT SMALLINT data as NULL */
is_null= 1;

/* Execute the INSERT statement - 1*/
if (mysql_stmt_execute(stmt))   //執行預處理環境  插入第一條記錄
{
  fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

/* Get the total number of affected rows */
affected_rows= mysql_stmt_affected_rows(stmt);  //獲取受影響的行信息
fprintf(stdout, " total affected rows(insert 1): %lu\n",
                (unsigned long) affected_rows);

if (affected_rows != 1) /* validate affected rows */
{
  fprintf(stderr, " invalid affected rows by MySQL\n");
  exit(0);
}

/* Specify data values for second row, then re-execute the statement */
int_data= 1000;
strncpy(str_data, "The most popular Open Source database", STRING_SIZE);
str_length= strlen(str_data);
small_data= 1000;         /* smallint */
is_null= 0;               /* reset */

/* Execute the INSERT statement - 2*/
if (mysql_stmt_execute(stmt))    //插入第二條記錄
{
  fprintf(stderr, " mysql_stmt_execute, 2 failed\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

/* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt); //有獲取受影響的行
fprintf(stdout, " total affected rows(insert 2): %lu\n",
                (unsigned long) affected_rows);

if (affected_rows != 1) /* validate affected rows */
{
  fprintf(stderr, " invalid affected rows by MySQL\n");
  exit(0);
}

/* Close the statement */
if (mysql_stmt_close(stmt))
{
  fprintf(stderr, " failed while closing the statement\n");
  fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
  exit(0);
}

 mysql_close(connect);  

printf("hello...\n");
return ret;

看了以上MySQL C API執行SQL語句的一種方式介紹,希望能給大家在實際運用中帶來一定的幫助。本文由于篇幅有限,難免會有不足和需要補充的地方,大家可以繼續關注億速云行業資訊板塊,會定期給大家更新行業新聞和知識,如有需要更加專業的解答,可在官網聯系我們的24小時售前售后,隨時幫您解答問題的。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西城区| 定安县| 通山县| 三门县| 兴化市| 建平县| 丹东市| 和顺县| 唐山市| 吐鲁番市| 旺苍县| 姜堰市| 广西| 莱州市| 子洲县| 安乡县| 西畴县| 盐城市| 长葛市| 中西区| 沙河市| 永丰县| 武隆县| 西充县| 华亭县| 吴忠市| 武功县| 加查县| 吉安市| 阳泉市| 石河子市| 芒康县| 辰溪县| 赣榆县| 寿阳县| 延安市| 会昌县| 靖远县| 南澳县| 吴旗县| 嘉善县|