bitsCN.com
他们将讨论返回数据的语句,例如INSERT以及不返回数据的语句,例如UPDATE和DELETE。然后,他们将编写从数据库检索数据的简单程序
执行SQL语句
现在,我们已经有了一个连接,并且知道如何处理错误,是时候讨论使用我们的数据库来作一些实际工作了。执行所有类型的SQL的主关键字是mysql_query:
int mysql_query(MYSQL *connection, const char *query)
正如您所见,它非常简单。它取一个指向连接结构的指针和包含要执行的SQL的文本字符串;与命令行工具不同,将不使用结束分号。成功之后,返回0。在需要包含二进制数据的特殊情况下,可以使用相关的函数,mysql_real_query。虽然出于本章的目的,我们仅需要讨论mysql_query。
不返回数据的SQL语句
我们将先讨论UPDATE、DELETE和INSERT语句。因为它们不返回数据,所以更易于使用。
这里我们将介绍的另一个重要函数是检查受影响的行数的函数:
my_ulonglong mysql_affected_rows(MYSQL *connection);
可能关于这一函数的最显而易见的事就是其非同寻常的返回结果。由于可移植性原因,这是一个特殊的无符号类型。为了在printf中使用,建议将其强制转换成使用%lu格式规范的无符号长整数。这个函数返回受以前的UPDATE、INSERT或DELETE查询影响的行数,这些查询是使用mysql_query执行的。
通常对于mysql_函数,返回码0表示没有行受影响;正数表示实际结果,通常是受影响的行数。
如前所述,当使用mysql_affected_rows时可能出现未期望的结果。让我们先讨论受INSERT语句影响的行数,它将按预期进行操作。将下列代码添加到程序 connect2.c 中,并且称其为insert1.c:
#include
#include
#include "mysql.h"
int main(int argc, char *argv[]) {
MYSQL my_connection;
int res;
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost",
"rick", "bar", "rick", 0, NULL, 0)) {
printf("Connection success/n");
res = mysql_query(&my_connection,
"INSERT INTO children(fname,age),
VALUES('Ann',3)");
if (!res) {
printf("Inserted %lu rows/n",
(unsigned long)mysql_affected_rows(&my_connection));
} else {
fprintf(stderr, "Insert error %d: s/n",mysql_errno ,
(&my_connection),
mysql_error(&my_connection));
}
mysql_close(&my_connection);
} else {
fprintf(stderr, "Connection failed/n");
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Connection error %d: %s/n",
mysql_errno(&my_connection),
mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
正如预期,插入的行数为1。
现在,我们更改代码,所以 'insert' 部分被替换成:
mysql_errno(&my_connection), mysql_error(&my_connection));
}
}
res = mysql_query(&my_connection, "UPDATE children SET AGE = 4
WHERE fname = 'Ann'");
if (!res) {
printf("Updated %lu rows/n",
(unsigned long)mysql_affected_rows(&my_connection));
} else {
fprintf(stderr, "Update error %d: %s/n",
mysql_errno(&my_connection),
mysql_error(&my_connection));
}
现在假设子表中有的数据,如下:
childno | fname | age |
1 2 3 4 5 6 7 8 9 10 11 |
Jenny Andrew Gavin Duncan Emma Alex Adrian Ann Ann Ann Ann |
14 10 4 2 0 11 5 3 4 3 4 |
if (mysql_real_connect(&my_connection, "localhost",
"rick", "bar", "rick", 0, NULL, CLIENT_FOUND_ROWS)) {
如果我们在数据库中复位数据,然后运行带有这种修改的程序,则它报告的行数为4。
函数mysql_affected_rows还有最后一个奇怪之处,它发生在从数据库中删除数据时。如果使用WHERE子句,则mysql_affected_rows将按预期返回删除行数。但是,如果没有WHERE子句,则删除所有行,报告受影响的行数却为0。这是因为由于效率原因优化删除整个表。这种行为不受CLIENT_FOUND_ROWS选项标志的影响。
返回数据的语句
现在是时候讨论SQL的最普遍用法了,从数据库检索数据的SELECT语句。
MySQL 还支持返回结果的SHOW、DESCRIBE和EXPLAIN SQL语句,但是这里不考虑它们。按惯例,手册中包含这些语句的说明。
您将会从PostgreSQL章记起,可以从PQexec中的SQL SELECT 语句检索数据,这里马上获取所有数据,或者使用游标从数据库中逐行检索数据,以便搞定大数据。
由于完全相同的原因,MySQL的检索方法几乎完全相同,虽然它实际上不用游标的形式描述逐行检索。但是,它提供了缩小这两种方法间差异的API,如果需要,它通常使两种方法的互换更加容易。
通常,从MySQL数据库中检索数据有4个阶段:
发出查询
检索数据
处理数据
执行所需的任何整理
象以前一样,我们使用mysql_query发出查询。数据检索是使用mysql_store_result或mysql_use_result完成的,这取决于想如何检索数据,随后使用mysql_fetch_row调用序列来处理数据。最后,必须调用mysql_free_result以允许MySQL执行任何所需的整理。
全部立即数据检索的函数
可以从SELECT语句(或其他返回数据的语句)中检索完所有数据,在单一调用中,使用mysql_store_result:
MYSQL_RES *mysql_store_result(MYSQL *connection);
必须在mysql_query检索数据后才能调用这个函数,以在结果集中存储该数据。这个函数从服务器中检索所有数据并立即将它存储在客户机中。它返回一个指向以前我们从未遇到过的结构(结果集结构)的指针。如果语句失败,则返回NULL。
使用等价的PostgreSQL时,应该知道返回NULL意味着已经发生了错误,并且这与未检索到数据的情况不同。即使,返回值不是NULL,也不意味着当前有数据要处理。
如果未返回NULL,则可以调用mysql_num_rows并且检索实际返回的行数,它当然可能是0。
my_ulonglong mysql_num_rows(MYSQL_RES *result);
它从mysql_store_result取得返回的结果结构,并且在该结果集中返回行数,行数可能为0。如果mysql_store_result成功,则mysql_num_rows也总是成功的。
这种mysql_store_result和mysql_num_rows的组合是检索数据的一种简便并且直接的方法。一旦mysql_store_result成功返回,则所有查询数据都已经存储在客户机上并且我们知道可以从结果结构中检索它,而不用担心会发生数据库或网络错误,因为对于程序所有数据都是本地的。还可以立即发现返回的行数,它可以使编码更简便。如前所述,它将所有结果立即地发送回客户机。对于大结果集,它可能耗费大量的服务器、网络和客户机资源。由于这些原因,使用更大的数据集时,最好仅检索需要的数据。不久,我们将讨论如何使用mysql_use_result函数来完成该操作。
一旦检索了数据,则可以使用mysql_fetch_row来检索它,并且使用mysql_data_seek、mysql_row_seek、mysql_row_tell操作结果集。在开始检索数据阶段之前,让我们先讨论一下这些函数。
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
这个函数采用从存储结果中获取的结果结构,并且从中检索单一行,在行结构中返回分配给您的数据。当没有更多数据或者发生错误时,返回NULL。稍后,我们将回来处理这一行中的数据。
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset);
这个函数允许您进入结果集,设置将由下一个获取操作返回的行。offset是行号,它必须在从0到结果集中的行数减 1 的范围内。传递0将导致在下一次调用mysql_fetch_row时返回第一行。
MYSQL_ROW_OFFEST mysql_row_tell(MYSQL_RES *result);
这个函数返回一个偏移值,它表示结果集中的当前位置。它不是行号,不能将它用于mysql_data_seek。但是,可将它用于:
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset);
它移动结果集中的当前位置,并返回以前的位置。
有时,这一对函数对于在结果集中的已知点之间跳转很有用。请注意,不要将row tell和row seek使用的偏移值与data_seek使用的行号混淆。这些是不可交换的,结果将是您所希望看到的。
void mysql_free_result(MYSQL_RES *result);
完成结果集时, 必须总是调用这个函数,以允许MySQL库整理分配给它的对象。
检索数据
现在开始编写从数据库中检索数据的第一个程序。我们将选择所有年龄大于5的行的内容。不幸的是我们还不知道如何处理这个数据,所以我们能做的只有循环检索它。这便是 select1.c:
#include
#include
#include "mysql.h"
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;
int main(int argc, char *argv[]) {
int res;
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, "localhost", "rick",
"bar", "rick", 0, NULL, 0)) {
printf("Connection success/n");
res = mysql_query(&my_connection, "SELECT childno, fname,
age FROM children WHERE age > 5");
if (res) {
printf("SELECT error: %s/n", mysql_error(&my_connection));
} else {
res_ptr = mysql_store_result(&my_connection);
if (res_ptr) {
printf("Retrieved %luows/n",(unsignedlong)mysql_num_rows(res_ptr));
while ((sqlrow = mysql_fetch_row(res_ptr))) {
printf("Fetched data.../n");
}
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Retrive error: s/n",mysql_error(&my_connection));
}
}
mysql_free_result(res_ptr);
}
mysql_close(&my_connection);
} else {
fprintf(stderr, "Connection failed/n");
if (mysql_errno(&my_connection)) {
fprintf(stderr, "Connection error %d: %s/n",
mysql_errno(&my_connection),mysql_error(&my_connection));
}
}
return EXIT_SUCCESS;
}
检索结果集并循环通过已检索的数据的重要部分都已突出显示。
一次检索一行数据
要按需要逐行检索数据,而不是立即获取全部数据并将它存储在客户机中,可以将mysql_store_result调用替换成 mysql_use_result:
MYSQL_RES *mysql_use_result(MYSQL *connection);
这个函数还取得一个连接对象并返回结果结合指针,或者出错时返回NULL。与mysql_store_result相似,它返回指向结果集对象的指针;关键的不同点在于返回时,实际上没有将任何数据检索到结果集,只是初始化结果集以准备好检索数据。
参考资料
您可以参阅本文在developerWorks全球站点上的英文原文.
本文章取自Wrox Press Ltd出版的Professional Linux一书的第5章。
关于作者
Rick Stones是一位系统设计师,他在一家大型泛欧制药分销和分配公司的IT部门工作。从1985年开始,他一直在使用各种形式的 UNIX,并且发现带有早期 .99 CD-ROM发行版的Linux。他用各种语言编写UNIX、Linux和其它平台的软件,同时还安装并管理几台Linux服务器。在非常有限的业余时间,他努力提高他的钢琴演奏技巧。
从大学时代开始接触C和UNIX V6时起,Neil Matthew对于UNIX和Linux已经超过20年的经验。从那时起他就在IT业工作,主要从事通信软件的开发,一直保持对于深奥的编程语言和开发技术的热情。现在,他作为系统设计师,对技术战略和QA提出建议。他热心于在公司企业内建立Linux商业案例。业余时间,写作或骑马为乐,Neil努力劝说他的妻子和两个孩子与他一起在乡间散步。Neil参与编写了Wrox Press发行的好几本书,最著名的是共同著作了Beginning Linux Programming和Professional Linux Programming。bitsCN.com

本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于索引优化器工作原理的相关内容,其中包括了MySQL Server的组成,MySQL优化器选择索引额原理以及SQL成本分析,最后通过 select 查询总结整个查询过程,下面一起来看一下,希望对大家有帮助。

sybase是基于客户/服务器体系结构的数据库,是一个开放的、高性能的、可编程的数据库,可使用事件驱动的触发器、多线索化等来提高性能。

visual foxpro数据库文件是管理数据库对象的系统文件。在VFP中,用户数据是存放在“.DBF”表文件中;VFP的数据库文件(“.DBC”)中不存放用户数据,它只起将属于某一数据库的 数据库表与视图、连接、存储过程等关联起来的作用。

数据库系统由4个部分构成:1、数据库,是指长期存储在计算机内的,有组织,可共享的数据的集合;2、硬件,是指构成计算机系统的各种物理设备,包括存储所需的外部设备;3、软件,包括操作系统、数据库管理系统及应用程序;4、人员,包括系统分析员和数据库设计人员、应用程序员(负责编写使用数据库的应用程序)、最终用户(利用接口或查询语言访问数据库)、数据库管理员(负责数据库的总体信息控制)。

microsoft sql server是Microsoft公司推出的关系型数据库管理系统,是一个全面的数据库平台,使用集成的商业智能(BI)工具提供了企业级的数据管理,具有使用方便可伸缩性好与相关软件集成程度高等优点。SQL Server数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使用户可以构建和管理用于业务的高可用和高性能的数据应用程序。

结构层次是“数据库→数据表→记录→字段”;字段构成记录,记录构成数据表,数据表构成了数据库。数据库是一个完整的数据的记录的整体,一个数据库包含0到N个表,一个表包含0到N个字段,记录是表中的行。

go语言可以写数据库。Go语言和其他语言不同的地方是,Go官方没有提供数据库驱动,而是编写了开发数据库驱动的标准接口,开发者可以根据定义的接口来开发相应的数据库驱动;这样做的好处在于,只要是按照标准接口开发的代码,以后迁移数据库时,不需要做任何修改,极大方便了后期的架构调整。

mysql查询为什么会慢,关于这个问题,在实际开发经常会遇到,而面试中,也是个高频题。遇到这种问题,我们一般也会想到是因为索引。那除开索引之外,还有哪些因素会导致数据库查询变慢呢?


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版
SublimeText3 Linux最新版