??xml version="1.0" encoding="utf-8" standalone="yes"?>
贴一D以前在windows上用mysql的代码?br />#include <stdio.h>
2#include <string.h>
3#include <winsock2.h>
4#include "mysql.h"
5
6#pragma comment(lib,"libmySQL.lib")
7
8void main()
{
9 MYSQL *mysql;
10 MYSQL_RES *res;
11 MYSQL_ROW row;
12 char *query;
13 int t,r;
14
15
16 mysql=mysql_init(mysql);
17 if (!mysql_real_connect(mysql,"localhost","root","","ceshi",0,NULL,0))
18
{
19 printf( "Error connecting to database: %s\n",mysql_error(mysql));
20 }
21 else
22 printf("Connected
\n");
23
24 query="Insert Into admin(username,password) values('whoami','iampf')";
25 t=mysql_real_query(mysql,query,(unsigned int)strlen(query));
26 if(t)
27
{
28 printf("Insert Error:%s\n",mysql_error(mysql));
29 }
30
31 query="select * from admin";
32 t=mysql_real_query(mysql,query,(unsigned int) strlen(query));
33 if (t)
34
{
35 printf("Error making query: %s\n",
36 mysql_error(mysql));
37 }
38 else printf("Query made
\n");
39 res=mysql_use_result(mysql);
40 for(r=0;r<mysql_field_count(mysql);r++)
{
41 row=mysql_fetch_row(res);
42 if(row<0) break;
43 for(t=0;t<mysql_num_fields(res);t++)
{
44 printf("%s ",row[t]);
45 }
46 printf("\n");
47 }
48 mysql_close(mysql);
49}
50
51
]]>
曾以为Windows版本的MySQL存在不能使用UDF的BUG诸提交了一个bug报告。不q?br />g发现是我搞错了,MySQL的技术支持h员给了非常完的解答Q同大家分n
一下。下Ҏ原文回复 :)
Sorry this isn't a bug.
Below I pasted a sample I did sometime ago for another user:
Ok. Assuming you have VC++ and the source distribution and a server
running,
I will create a UDF that returns a name:
Note: the sample is ugly, but the purpose here is to show you how
to handle the UDF.
- Open the mysqld.dsw workspace.
- Add New project to the workspace
- Project name: my_udf
- Select Win32 Dynamic-Link Library
- Click OK
- Select An Empty DLL project
- Click Finish
- Click OK
- Add a new file called my_udf.cpp to the project:
#include <stdlib.h>
#include <winsock.h>
#include <mysql.h>
extern "C" {
char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error);
}
char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error)
{
char * me = "my name";
return me;
}
- Type Ctrl+N for to create a new file.
- Select text type
- File name: my_udf.def
- Edit the above file with the below contents:
LIBRARY UDF_EXAMPLE
DESCRIPTION 'Example Using UDF with VC++'
VERSION 1.0
EXPORTS
my_name
- Right Click the my_udf project and select Settings
- Click the C/C++ tab
- Select General in the Category Combo
- Add the macro HAVE_DLOPEN to the PreProcessor definition
- Select Preprocessor in the Category Combo
- Add the include path to the text box: Additional Include directories
e.g: ../include
- Press F7 for to build the DLL.
- Copy the my_udf.dll to the environment path directory:
\winnt\system32 for example.
- Start the mysql client and issue:
C:\mysql-udf\bin>mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2 to server version: 3.23.52-max-nt
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";
Query OK, 0 rows affected (0.08 sec)
mysql> select my_name();
mysql> drop function my_name;
Query OK, 0 rows affected (0.00 sec)
画蛇添的作下简要中文说明?br />
抱歉Q这q不是一个bug。下面我_脓一个以前ؓ某个客户做的例,假设你有?br />VC++,源码分发Qƈ且有一个正常运行的MySQL服务器?br />
我将创徏一个UDF它将一个名字:
注意Q例子非常简陋,目的是让你了解该如何处理手头的UDF?br />
- 打开 mysqld.dsw 工作区?br />- d新项目到q个工作?br />- Project name: my_udf // 目名称:my_udf
- 选择 Win32 Dynamic-Link Library // Win32动态连接库
- 点击 OK
- 选择 An Empty DLL project // 一个空DLL目
- 点击 Finish
- 点击 OK
- d新文?my_udf.cpp 到项目中:
#include <stdlib.h>
#include <winsock.h>
#include <mysql.h>
extern "C" {
char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error);
// 兼容C
}
char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error)
{
char * me = "my name";
return me;
// 调用此UDF返?my name
}
- ?Ctrl+N 来创Z个新文g?br />- 选择 text cd
- File name: my_udf.def file://文g名:my_udf.def
- 按照下边的内容编辑文件?br />LIBRARY UDF_EXAMPLE
DESCRIPTION 'Example Using UDF with VC++'
VERSION 1.0
EXPORTS
my_name
- 叛_my_udf目q择Settings
- ?C/C++ 选项?br />- 选择 General
- d?HAVE_DLOPE 到预处理器定?br />- 选择 Preprocessor
- d头文件\? Additional Include directories
例如: ../include
- ?F7 ȝ译成 DLL.
- 复制 my_udf.dll 到环境变量path定义q的目录
比如 \winnt\system32 ?br />
- 打开mysql客户?br />
C:\mysql-udf\bin>mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2 to server version: 3.23.52-max-nt
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";
Query OK, 0 rows affected (0.08 sec)
mysql> select my_name();
mysql> drop function my_name;
Query OK, 0 rows affected (0.00 sec)
ok!Ƣ迎大家来MySQL板交UDF设计l验Q我的电子邮件是HeartIcy@163.comQ?br />手机13706410308。同Ӟ我们MySQL板准备开始系l化持箋性翻译MySQL文档Q?br />希望大家多多支持共同完成q一目?br />
HeartIcy
2003q??7日于中国南
MySQL对于成ؓ一个非常快速的数据库服务器有着当之无愧的名壎ͼ它也非常Ҏ讄和用。随着它作为网站后端数据库得声望日增,其效果在d开始有明显提高。但是很多MySQL用户更多地知道如何创Z个数据库q编写对它的查询。就像成千上万的人通过载闲暇时用Linux做实验来学习Unix那样Q很多h通过玩MySQL学习关系数据库。这些MySQL新手的大多数既没有关pL据库理论的背景,又没有时间阅读MySQL手册全文?i>
因此Q我们决定研I某些方法,你可以用针对优化性能来调节MySQL。在d本文后,你将理解一些帮助你设计你的MySQL数据库和查询的技术,值得你的应用很有效率。我们将假定你熟悉MySQL和SQL基础Q但不假定你有这两方面的q博知识?/p>
只存储你需要的信息
q听上去是常识,但h们常帔R取“厨房下水道”的方式q行数据库设计。他们认为可能项要得每样东西都要存储q设计数据库保存所有者这些数据。你需要对你的需求现实些Qƈ定取确实需要什么信息。你常常能随意生一些数据而不把它存在数据库表中。在q种情况下,从一个应用开发者的角度看也有道理这样做?/p>
例如Q在U目录的产品表可能包含各U品的名称、介l、尺寸、重量和h。除了h|你可能想存储每个目相关的税和运输成本。但实际上不必这样做。首先税和运输成本可以方便地Q由你的应用或MySQLQ计出来。其ơ,如果E和q输成本改变了,你可能必ȝ写必要的查询更新每个产品记录中的E和q输的费率?/p>
有时Z认ؓq太难不能在以后往数据库表中加入字D,所以他们感觉不得不定义可能多的列。这是明昄概念错误。在MySQL中,你可以用ALTER TABLE命o方便C改表定义以适应你改变的需求?/p>
例如Q如果你H然认识C需要给你的产品表增加一个别列Q可能你惛_许用户在你的目录中给产品评Q,你可以这样做Q?/p>
ALTER TABLE products ADD rank INTEGER
q给你的产品表增加了一个整数类型的U别列,你能用ALTER TABLE做什么的完整介绍参见MySQL手册?/p>
只要求你需要的东西--要清?/p>
像说“只存储你需要的东西”那Pq可能看来是常识Q但q一点常常被忽视Qؓ什么呢Q因为在一个应用开发时Q需求经常改变,所以很多查询最l看来是q样Q?/p>
SELECT * FROM sometable
当你不能肯定你将需要哪一列时Q要求所有列明显是最省力的事情,然而随着你的表不断增大和修改Q这可能变成一个性能问题。最好是在你的最初开发完成后再花些时间ƈ定你真正从你的查询中需要什么:
SELECT name, rank, description FROM products
q带来了一个相关的观点Q即代码l护比性能更重要。大多数变成语言QPerl、Python、PHP、Java{)允许通过字段名和数字~号讉K一条查询的l果Q这意味着你可以访问命名字D|字段Q都可以得到相同的数据?/p>
长期看,最好用列名而不是其~号位置Qؓ什么?因ؓ一个表中或一条查询中地列的相对位|可以改变。它们在表中可能因ؓ重复使用ALTER TABLE而改变,它们在查询中因重写了查询而忘记更新应用逻辑来匹配而改变?/p>
当然Q你仍然需要小心改变列名!但如果你使用列名而非标号位置Q如列名改变Q你可以用grep搜烦源代码或使用~辑器的搜烦能力查找你需要修改的代码?/p>
规范化你的表l构
如果你以前从未听说过“数据规范化”,不要x。规范化可能是一个复杂的专题Q你可以从只理解最基本的规范化概念中正真正L?/p>
理解它的最Ҏ的方法是认ؓ你的表是一个电子报表。如果你想以一个报表跟t你的CD收藏Q你可以如图Q种那样q行设计Q?/p>
图1
album track1 track2 track10
----- ------ ------ -------
Billboard Top Hits - 1984 Loverboy Shout St. Elmo's Fire
(Billy Ocean) (Tears for Fears) (John Parr)
q看上去很合理。大多数CD只有10首曲子,对否Q不然。如果你拥有一张有100首曲子的CD且几张超q?0首改怎么办。这意味着用这U方法,在极端的情况下,你将需要一个非常宽的表|或一个超q?00个字D늚表)来保存所有的数据?/p>
规范化表l构的目标是低쀜空单元”的数量最,在上qCD表的情况下,如果你允许CD可能包含100首曲子,你会有很多这LI单元。不你何时处理可能扩展到类DCD表那h量的字段列表Q它是你需要将你的数据分割?个或更多表的标志Q然后你一赯问ƈ获得你需要的数据?/p>
很多关系数据库的新手不真正知道关pL据库理pȝ中关pL什么。简单地_像一l信息存在可以基于共性数据联l(JOINQ在一L不同表中Q很不幸Q这听上L学术化和含糊Q但CD数据库提Z一个具体情况,我们可以研究如何规范数据?/p>
每个CD列表有一个固定的属性(标题、艺术家、年份、分c)集和一个不定的属性(曲目表)集的理解l了我们一些如何分成成能相互关联的表的思\?/p>
你可以创Z个所有专辑及其固定属性的表,另一个包含这些专辑的所有曲目的表。这样不是水qx考(像表|Q你垂直思?-好像你创徏列表而不是行--q徏立一个如?的表l构Q?br />
专辑的编PMySQL镜自动ؓ你生成,因ؓ我们在列上用了AUTO_INCREMENT属性)兌不同曲目Cl定专辑Qtracks表中的album_id字段匚w专辑表中的一个id。这栯获得l定专辑的所有曲目,你应该用如下查询Q?/font>
SELECT tracks.num, tracks.name
FROM albums, tracks
WHERE albums.title = 'Billboard Top Hits - 1984'
AND albums.id = tracks.album_id
该结构即灉|又有效。灵zL来自你可以在以后将数据加入pȝ而不必重C已完整的工作的事实。例如,如果你想增加每一张专辑的艺术家信息,你可以床架一个artists表,兌到albums表,像tracks那样。你无需修改现有的结?-只是增加它?/p>
有效性来自于在你的数据中没有明显的数据重复且没有大量的空z(I单元)的实施。这样MySQL在你的数据库表中既不存储多余的数据,也不比花额外的精力搜索大量空区域?/p>
如果你对关系数据库是新手Q规范化你的数据看v来有点奇怪,但在存储和检索数据时Q它使MySQL非常有效Qƈl予你扩展和伸羃你的应用却不必多ơ重构你的数据库的灵zL。尽可能早的花时间想清楚数据库设计,q考虑你的需求怎样随时间增长,前期q旉永远是值得的?/p>
复合索引
复合索引Q有时称l合索引Q是急于多个列的单一索引。MySQL在处理一条查询时每个表只使用一个烦引,q意味着如果你有多个l常出现在WHERE子句中的列,你可能要通过创徏一个复合烦引来加快q些查询?/p>
考虑下列表结构片断:
CREATE TABLE people (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
favorite_color VARCHAR(10) NOT NULL,
.
.
.
);
如果你常常基于last_name和first_name查询表,你可以从last_name和first_name的复合烦引中LQ?/p>
INDEX last_first (last_name, first_name)
׃MySQL构徏复合索引的方式,它可以用last_first索引来回{基于last_name本n或last_name与first_name两者的索引。这是因为如果列涉及复合索引的“最左前~”的形式QMySQL只使用一个复合烦引?/p>
所以如果一个复合烦引有多个列合成:
INDEX big_index (a, b, c, d, e, f, g, h, i)
MySQL可以用它来回{基于a、或a和b、或a和b和c、或a和b和c和d的查询。但它不能用big_index处理Ze、或c和f、或g和i的查询,因ؓq些序列没有一个是从烦引的最左边开始的?/p>
复合索引被用于加快某些复杂查询Q但你需要理解v局限,而且你永q应该进行一些测试,而不是简单地假设q样一个烦引将会有帮助?/p>
使用索引加快查询
当MySQL试图回达一条查询时Q它查看有关你的数据的各U统计,q决定如何以最快的速度扑և你想要的数据。对于前节的查询,MySQL读取albums表的所有titlesq把它们与“Billboard Top Hits --1984”进行比较看是否匚w。它一旦找C个匹配还不能停止Q因为有相同曲目的专辑不止一个(如你可以?2张CD标有“Greatest Hits”)Q结果MySQL必须d表中的每一行。这常称为“全表扫描”且可以避免?/p>
你应该避免全表扫描,因ؓQ?/p>
CPU开销Q如果你没有很多专辑Q检查所有这些标题的处理相对快些。但如果你需要在你的数据库中存储很多专辑呢?你有的专辑越多,q旉长。在专辑数量或检查它们所q旉旉存在一U线性关pR?i>
q发性:在MySQL正在从表中读取数据时Q它锁定表得没有其他h可以写入Q但可以d。当MySQL更新或删除表中的行时Q它锁定表得没有其他h可以从它d?i>
盘开销Q在一个大数据表上Q一ơ全表扫描将消耗大量磁盘I/O。这可能明显地减慢你的数据库服务?i> -- 特别是如果你的服务器是较慢的IDE驱动器?i>
最好是让全表扫描将到最?i> -- 特别是你的应用需要以规模或用h伸羃。MySQL最新版实有几个ƈ发性方面的改善QBDB、InnoDB和Gemini表类型)?/p>
在这里烦引可以帮助你Q简单地放一个,一个烦引允许MySQL很快地确定Q何给定值如“Billboard Top Hits -- 1984”是否将匚w表中的Q何行?/p>
怎样做到的呢Q当你告诉MySQL索引一个特定列Ӟ它在q后创徏另一个数据结构(索引Qƈ用它存储关于被烦引列中的值的某些额外信息Q被索引的值常UCؓ健码Q。这是一U简化,MySQL所有键码存储在一个树状数据结构中。该数据l构允许MySQL非常快速地扑ֈ特定键码?/p>
当MySQL发现列上有一个烦引,它将使用索引而不是执行一个全表扫描。这节省了CPU旉Q不必读取所有可能的|和磁盘I/OQ而且它改善了q发性,因ؓMySQL只锁定表_长的旉来获得所需的行Q基于它在烦引中找什么)。当你在表中有大量的数据Q最l的改善可能非常明显?/p>
对图3的albums表的CREATE TABLE语句的改q:
?
CREATE TABLE albums (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(80)NOT NULL,
INDEX title_idx (title)
);
正如你所见的Q语句只是简单地在定义后增加了一个INDEX行告诉MySQL在albums表中的title列上创徏名ؓtitle_idx的烦引。你可以l一个表增加多个索引Q就像你可在表中有多个列一栗单个烦引也可以有多个列合成?/p>
要给现有的表加上一个烦引而不是重Q你可以用ALTER TABLE命oQ?/p>
ALTER TABLE albums ADD INDEX title_idx (title)
查询处理
如果你的查询复杂QMySQL用于_定如何获取数据的原则可能变得难于理解。幸q的是,有几个一般原则和一条命令允怽获得正在做什么的更好的理解。首先,原则是:
如果MySQL定了简单地扫描全表更快些,则它L不使用索引。一般地Q如果一个烦引告诉MySQL讉K表中大概30%的行Q它攑ּ索引q简单地执行全表扫描?i>
如果多烦引可以用来满x询,MySQL用最严格的一?i> -- 卛_致最的行被提取的那个?i>
如果你正在选择的列是一个烦引的所有部分,MySQL可以直接从烦引中d锁需的数据,l不接触Q或锁定Q表本n?i>
当联l几个表ӞMySQL首先从可能q回最行的表中读取数据。你指定表的ơ序可能与MySQL使用它们的次序不同,q也影响到最l返回给你的行的ơ序Q所以如果你需要行以特定的ơ序出现Q要保证在你的查询中使用一个ORDER子句?i>
已经说了很多了,重要的是认识到MySQL所做的一些决{实际上是基于猜,像人类q行大量猜测一P偶尔也会出错?i>
如果你怀疑已l发生或只是想理解MySQL怎样处理一条查询,你可以用EXPLAIN命o。简单地在你的查询前面加上EXPLAINq个字,q要求MySQL执行它,MySQL不执行查询,相反报告有助于查询的候选烦引列表和所知道的有兛_们的一切?/p>
EXPLAIN输出的完整讨论参见MySQL参考手册?br />
不要q分使用索引
已经知道索引使查询更快,你可能們于烦引你表中的每个列。但是得益于索引的性能提高是有代h的,在表中每ơ执行INSERT、UPDATE、REPLACE或DELETEQMySQL不得不更新表上的每个索引以反映变化?/p>
那么你如何确定何旉用它们呢Q最常见的答案是“看情况”。它依赖你运行的查询cd和你q行它们的频度,它依赖于你的数据Q它依赖于你的期望和需求。你得到了答?i> -- 它依赖于很多事情?/p>
在列上有索引的理由是MySQL~窄其搜索范围以便尽可能会的匚w行(且避免全表扫描)。你可以认ؓ索引是对列中的每个唯一值只包含一V在索引中,MySQL必须考虑M重复|q些重复值稍微降低效率和索引的用途?/p>
所以在索引一个列之前Q考虑数据重复的百分比Q如果该癑ֈ比太高,你可能觉察不到用索引带来的Q何性能改善?/p>
要以更简明的术语描述Q它清楚地知道在albums表中索引曲目字段Q因为有可能有大量不同的|而且重复非常。但如果在albums表中有一个分cdQ烦引它则可能hg大,一般的CD攉包含多少不同的类型呢Q将会有很多重复的类型倹{?/p>
另一件要考虑的事情是你的查询可能使用的频度。MySQL只能对出现在一条查询种的WHERE子句中的特定列用烦引,试图回答查询Q?/p>
SELECT * FROM albums WHERE id = 500
MySQL不能使用在title上的查询Q该查询要求MySQLZ其id查找记录而不是其title?i>
如果你很用查询中WHERE子句中的一个列Q它可能不值得索引该列。可能在极少的情况下容h全表扫描比要求MySQL在每ơ修Ҏ保持索引更新M上更有效些?
有疑问时Q进行测试。你总能q行某些到烦引或不带索引的基准测试看哪一个更快,只要试图让你的基准测试逼真些。如果你的查询有20%是UPDATEQ?0%是SLEECTQ肯定你的基准测试能发映出来Q详见MySQL参考手册?/p>
使用REPLACE查询
有可能你惛_表中插入一条记录,除非它已l存在。如果记录已l存在,你想UPDATE它。不是重写代码中做这件事的逻辑Qƈ需q行多个查询Q而是MySQL使用REPLACE来做此项工作?/p>
如果id?的专辑假定有曲目“Shaking the Tree”,你可以这样写查询Q?/p>
REPLACE INTO albums valueS (6, 'Shaking the Tree')
重要的是理解REPLACE如何定一条记录是否在表中存在。MySQL在表上使用PRIMARY KEY或UNIQUE KEY来执行检查,如果都不存在QREPLACE效果上变成了INSERT?/p>
使用临时?/p>
当工作在非常大的表上Ӟ你可能偶需要运行很多查询获得一个大量数据的的子集Q不是对整个表运行这些查询,而是让MySQL每次扑և所需的少数记录,记录选择C个时表可能更快些,然后多这些表q行查询?/p>
创徏临时表很ҎQ给正常的CREATE TABLE语句加上TEMPORARY关键字:
CREATE TEMPORARY TABLE tmp_table (
name VARCHAR(10) NOT NULL,
value INTEGER NOT NULL
)
临时表将在你q接MySQL期间存在。当你断开ӞMySQL自动删除表q放所用的I间。当然你可以在仍然连接的时候删除表q攄间?/p>
DROP TABLE tmp_table
如果在你创徏名ؓtmp_table临时表时名ؓtmp_table的表在数据库中已l存在,临时表将有必要屏蔽(隐藏Q非临时表tmp_table?/p>
如果你声明时表是一个HEAP表,MySQL也允怽指定在内存中创徏它:
CREATE TEMPORARY TABLE tmp_table (
name VARCHAR(10) NOT NULL,
value INTEGER NOT NULL
) TYPE = HEAP
因ؓHEAP表存储在内存中,你对它运行的查询可能比磁盘上的时表快些。然而,HEAP表与一般的表有些不同,且有自n的限制。详见MySQL参考手册?/p>
正如前面的徏议,你应该测试时表看看它们是否真的比对大量数据库运行查询快。如果数据很好地索引Q时表可能一点不快?/p>
临时表在MySQL 3.23.0和更新版才有?/p>
只用最新版的MySQL
2001q一月中旬,MySQL 3.23宣布E_。除了后很多新功能外Q它也比3.22pd更快和更具~性?/p>
MySQL的更新版不断推出。如果你控制着你的MySQL服务器,最好是试保持版本相对最新。除了有最新功能和错误修正Q你常常会看到较新的MySQL发行有明昄性能提高?/p>
其他资源
除了阅读MySQL手册Q你也可以咨询:
你的DBAQ如果你在一个共享服务器上用MySQLQ某个h被指定ؓ数据库管理员QDBAQ,q是一个好Z。如果你的DBA非常熟悉MySQLQ它可能可以在分析和优化你的表结构和查询上帮你一下?i>
MySQL用户邮g列表Q有非常z跃的邮件列表,在其中MySQL用户l常彼此L帮助。新手和老手愿意分n其知识ƈ彼此帮助解决共同的问题。实际上Q有些MySQL开发团队成员很好地监视着邮g列表?i>
MySQL书籍Q不要与MySQL参考手册淆,Paul DuBois写了一本极好的书名为《MySQL》的书(有中文译本)?