This slide is based on Jeffrey D. Ullman's work, which can be download from his website.
这些查询有可能会从用户输入中获取常数.
粗心的代码可能会允许那些相当出乎意料的查询被构建和执行.
现在有关系
SELECT acct FROM Accounts WHERE name = n AND passwd = p
这里不同的语言有不同的处理方式.
在
CREATE TABLE Accounts( name VARCHAR(50), passwd VARCHAR(50), acct DECIMAL(20,2) );
插入一些数据.
INSERT INTO Accounts VALUE ("gates", "SecretString", 10000000000.10);
mysql> select * from Accounts; +-------+--------------+----------------+ | name | passwd | acct | +-------+--------------+----------------+ | gates | SecretString | 10000000000.10 | +-------+--------------+----------------+ 1 row in set (0.00 sec)
SELECT acct FROM Accounts WHERE name = 'gates' -- ' AND passwd = 'who cares?';
mysql> SELECT acct FROM Accounts WHERE name = 'gates' -- ' AND passwd = 'who cares?'; -> ; +----------------+ | acct | +----------------+ | 10000000000.10 | +----------------+ 1 row in set (0.00 sec)
对于常规语言连接数据库的第三种方式是利用库的调用.
一般大型数据库的通用环境有下面三层体系结构.
数据库中存储物品、顾客等的信息.
交易逻辑中包含了诸如“当某人点击了 'checkout' 后我该做什么”之类的事情.
在许多 DB-access 语言中, 数据库就是一个
数据库服务器维持一定数量的
应用服务器发布语句(statements): 通常是查询和更新.
这里我们并不象(如嵌套 SQL)那样利用预处理器, 而是使用函数库.
C 通过下面四种类型的结构(struct)来连接数据库:
句柄是记录的指针. 头文件
函数
SQLALLocHandle(SQL_HANDLE_STMT, myCon, &myStat);
#include "sqlcli.h" SQLHENV myEnv; /* 创建环境句柄 */ SQLHDBC myCon; /* 创建连接句柄 */ SQLHSTMT execStat; /* 创建语句句柄 */ SQLRETURN errorCode1, errorCode2, errorCode3; errorCode1=SQLALLocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &myEnv); if(!errorCode1){ errorCode2=SQLALLocHandle(SQL_HANDLE_DBC, myEnv, &myCon); if(!errorCode2){ errorCode3=SQLALLocHandle(SQL_HANDLE_STMT, myCon, &execStat); } }
上面最后创建了句柄为
与语句句柄相关联且执行 SQL 语句的进程与动态 SQL 很相似. 都是先准备(prepare)再执行(execute).
SQLPrepare(execStat, "SELECT beer, price FROM Sells WHERE bar='Joe''s Bar'", SQL_NTS); SQLExecute(execStat);
如果对于语句
请具体查询 sqlcli.h 文件
当执行的 SQL 语句是一个查询, 我们需要从结果关系中取出这些元组.
当我们取出一个元组后, 我们需要将该元组的组成部分(各个属性值)用到其他地方去.
每个组成部分通过函数
假设我们刚执行了
SELECT beer, price FROM Sells WHERE bar='Joe''s Bar'
将所得元组的两个分量值绑定到变量
SQLBindCol(execStat,1,,&theBeer,,); SQLBindCol(execStat,2,,&thePrice,,);
现在, 我们利用循环可以取出所有的元组.
while(SQLFetch(execStat)!=SQL_NO_DATA) { /* do something with theBeer and thePrice */ }
在数据库中新建一个名为 test_db3 的数据库.
#include <my_global.h> #include <mysql.h> int main(int argc, char **argv) { MYSQL *conn; conn = mysql_init(NULL); if (conn == NULL) { printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } if (mysql_real_connect(conn, "localhost", "haifeng", "34klq*", NULL, 0, NULL, 0) == NULL) { printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } if (mysql_query(conn, "create database test_db3")) { printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } mysql_close(conn); }
使用 gcc 编译
gcc version.c -o version `mysql_config --cflags --libs`
如果出现下面的提示:
In file included from /usr/include/pthread.h:21:0, from /usr/include/mysql/my_global.h:274, from connect.c:1: /usr/include/features.h:330:4: 警告:#warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp]
则在刚才的编译命令中加一个 -O 参数, 即
gcc version.c -o version `mysql_config --cflags --libs` -O
连接数据库 test_students, 打印 studentinfo 表中的内容.
将下面的文件保存为
/** * 连接MySQL, 注意如果连接的是远程服务器, 注意密码保护. * 假设本地安装的是 WampServer, 编译时需要包含其中的头文件以及链接到相应的库文件. */ #include <stdio.h> #include <stdlib.h> //#include <winsock2.h> #include "C:/wamp64/bin/mysql/mysql5.7.23/include/mysql.h" void finish_with_error(MYSQL *con) { fprintf(stderr, "%s\n", mysql_error(con)); printf("Error %u: %s\n", mysql_errno(con), mysql_error(con)); mysql_close(con); exit(1); } int main(int argc, char **argv) { //注意:这里打印的版本与所使用的库有关. 如果本地开启的MySQL是5.6.17,仍会显示库所用的版本5.5.27 printf("MySQL local client version: %s\n", mysql_get_client_info()); MYSQL *conn; conn = mysql_init(NULL); if (conn == NULL) { //fprintf(stderr, "mysql_init() failed\n"); printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); exit(1); } //连接远程服务器需要用的参数 const char* HOST="远程服务器的IP地址";//或者连接"localhost"作测试 const char* User="数据库用户名"; const char* Password="该用户的数据库密码"; const char* Database="test_students";//待连接的数据库名称 unsigned int Port=3306; if (mysql_real_connect(conn, HOST, User, Password, Database, Port, NULL, 0) == NULL) { finish_with_error(conn); } printf("connect to Host: %s sucessfully\n", HOST); printf("MySQL remote client version: %s\n", mysql_get_client_info()); mysql_query(conn, "SET NAMES GBK;"); if (mysql_query(conn, "select * from studentinfo;")) { printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); finish_with_error(conn); } printf("MySQL client version: %s\n", mysql_get_client_info()); MYSQL_RES *result = mysql_store_result(conn); if (result == NULL) { finish_with_error(conn); } int num_fields = mysql_num_fields(result); printf("num of fields: %d\n", num_fields); MYSQL_ROW row; while ((row = mysql_fetch_row(result))) { for(int i = 0; i < num_fields; i++) { printf("%s ... ", row[i] ? row[i] : "NULL"); } printf("\n"); } printf("------\n"); mysql_free_result(result); mysql_close(conn); return 0; }
g++.exe -Wall -fexceptions -g -IC:\wamp64\bin\mysql\mysql5.7.23\include -c D:\work\cs\c++\database\mysql\mysql-c-connect\main.cpp -o obj\Debug\cs\c++\database\mysql\mysql-c-connect\main.o g++.exe -o bin\Debug\mysql-connect.exe obj\Debug\cs\c++\database\mysql\mysql-c-connect\main.o C:\wamp64\bin\mysql\mysql5.7.23\lib\libmysql.lib
g++.exe -Wall -fexceptions -O2 -I"C:\Program Files (x86)\MySQL\MySQL Server 5.5\include" -c D:\work\cs\c++\database\mysql\mysql-c-connect\main.cpp -o obj\Release\cs\c++\database\mysql\mysql-c-connect\main.o g++.exe -o bin\Release\mysql-connect.exe obj\Release\cs\c++\database\mysql\mysql-c-connect\main.o -s C:\wamp64\bin\mysql\mysql5.7.23\lib\libmysql.lib
类似于
import java.sql.*; Class.forName(com.mysql.jdbc.Driver); Connection myCon = DriverManager.getConnection( <URL>, <username>, <password> );
JDBC 提供了两个类:
这个连接类(Connection class) 有
Statement stat1 = myCon.createStatement(); PreparedStatement stat2 = myCon.createStatement( "SELECT beer, price FROM Sells " + "WHERE bar = 'Joe''s Bar' " );
JDBC 根据具体更改(也称为“更新”)来将查询分类.
之前定义的
stat1.executeUpdate( "INSERT INTO Sells " + "VALUES('Brass Rail','Bud',3.00)" );
ResultSet menu = stat2.executeQuery();
方法
当
方法
即
使用下面的循环从每一个元组中得到
while ( menu.next() ) { theBeer = menu.getString(1); thePrice = menu.getFloat(2); /*something with theBeer and thePrice*/ }
References:
http://zetcode.com/db/mysqljava/
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package helloworld; import java.util.Date; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author haife */ public class HelloWorld { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here System.out.println("Hello Java!\n The Date and Time is: "); System.out.println(new Date()); Connection con = null; Statement st = null; ResultSet rs = null; String url = "jdbc:mysql://localhost:3306/test_bar"; String user = "root"; String password = "34klq*"; try { con = DriverManager.getConnection(url, user, password); st = con.createStatement(); rs = st.executeQuery("SELECT * FROM Bars"); System.out.println("name\t addr\t license\n"); while(rs.next()) { System.out.println(rs.getString(1)+"\t"+rs.getString(2)+"\t"+rs.getString(3)); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(HelloWorld.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } finally { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(HelloWorld.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } } }
package ExamplePackage; import java.sql.*; import java.util.*; public class ConnectionManager { static Connection con; static String url; public static Connection getConnection() { try { //String ipAddr="127.0.0.1"; //String port="5432"; //String dbname="test_db"; //String url = "jdbc:postgresql://"+ipAddr+":"+ port + "/"+dbname; String url = "jdbc:postgresql://127.0.0.1:5432/test_db"; // assuming "DataSource" is your DataSource name Class.forName("org.postgresql.Driver"); try { con = DriverManager.getConnection(url,"postgres",""); // assuming your SQL Server's username is "username" // and password is "password" } catch (SQLException ex) { ex.printStackTrace(); } } catch(ClassNotFoundException e) { System.out.println(e); } return con; } }
PHP 解决了很多语言都碰到的非常重要的问题, 即.
PHP 的解决办法是: 双引号括起来的变量在引用时用它的值替代, 单引号则忠实地表示字符串.
$100 = "one hundred dollars"; $sue = 'You owe me $100.'; $joe = "You owe me $100.";
PHP 有两种数组:
数字型数组用下标
关联数组
若
一个环境可以表示成一个关联数组, 例如:
$myEnv = array ( "phptype" => "oracle", "hostspec" => "www.stanford.edu", "database" => "cs145db", "username" => "ullman", "password" => "notMyPW" );
在导入 DB library 及上面的
$myCon = DB::connect($myEnv);
它的参数是字符串. 当发生错误时返回一个错误码, 当成功时返回一个关系.
对于给定的变量
$beer = 'Bud'; $result = $myCon->query( "SELECT bar FROM Sells " . " WHERE beer = $beer;");
while ($bar=$result->fetchRow()){ //do something with $bar }
使用mysqli
<?php $servername = "localhost"; $username = "root"; $password = "34klq*";//更改为你使用的mysql服务器密码 $dbname = "test_bar";//"urlsdb"; $conn = new mysqli($servername, $username, $password, $dbname); echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"; echo "<html>"; echo "<head><title>测试连接MySQL</title>"; echo "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />"; echo "</head><body>"; if ($conn->connect_error){ die("连接失败: ".$conn->connect_error); }else{ print("Successfully connected to MySQL! <br/>The database is: <b>".$dbname."</b><br/><br/><hr/>"); @mysqli_query($conn, "set names 'utf8'");//最好加一下,不然会有乱码 @mysqli_select_db($dbname, $conn); $sql2="SELECT * FROM Bars"; $result=mysqli_query($conn,$sql2); echo "<table border=1>"; while($row=mysqli_fetch_assoc($result)) { echo "<tr><td>".$row['name']."</td>"; echo "<td>".$row['addr']."</td>"; echo "<td>".$row['license']."</td></tr>"; } echo "</table>"; } echo "</body></html>"; ?>