
本文阐述了怎么使用DBMS存储过程 阐述了使用存储过程的基本的和高级特性 比如返回ResultSet 本文假设你对DBMS和JDBC已经非常熟悉 也假设你能够毫无障碍地阅读其它语言写成的代码(即不是Java的语言) 但是 并不要求你有任何存储过程的编程经历
存储过程是指保存在数据库并在数据库端执行的程序 你可以使用特殊的语法在Java类中调用存储过程 在调用时 存储过程的名称及指定的参数通过JDBC连接发送给DBMS 执行存储过程并通过连接(如果有)返回结果
使用存储过程拥有和使用基于EJB或CORBA这样的应用服务器一样的好处 区别是存储过程可以从很多流行的DBMS中免费使用 而应用服务器大都非常昂贵 这并不只是许可证费用的问题 使用应用服务器所需要花费的管理 编写代码的费用 以及客户程序所增加的复杂性 都可以通过DBMS中的存储过程所整个地替代
你可以使用Java Python Perl或C编写存储过程 但是通常使用你的DBMS所指定的特定语言 Oracle使用PL/SQL PostgreSQL使用pl/pgsql DB 使用Procedural SQL 这些语言都非常相似 在它们之间移植存储过程并不比在Sun的EJB规范不同实现版本之间移植Session Bean困难 并且 存储过程是为嵌入SQL所设计 这使得它们比Java或C等语言更加友好地方式表达数据库的机制
因为存储过程运行在DBMS自身 这可以帮助减少应用程序中的等待时间 不是在Java代码中执行 个或 个SQL语句 而只需要在服务器端执行 个存储过程 网络上的数据往返次数的减少可以戏剧性地优化性能
使用存储过程
简单的老的JDBC通过CallableStatement类支持存储过程的调用 该类实际上是PreparedStatement的一个子类 假设我们有一个poets数据库 数据库中有一个设置诗人逝世年龄的存储过程 下面是对老酒鬼Dylan Thomas(old soak Dylan Thomas 不指定是否有关典故 文化 请批评指正 译注)进行调用的详细代码
try{ int age = ; String poetName = dylan thomas ; CallableStatement proc = connection prepareCall( { call set_death_age( ) } ); proc setString( poetName); proc setInt( age); cs execute();}catch (SQLException e){ // }
传给prepareCall方法的字串是存储过程调用的书写规范 它指定了存储过程的名称 ?代表了你需要指定的参数
和JDBC集成是存储过程的一个很大的便利 为了从应用中调用存储过程 不需要存根(stub)类或者配置文件 除了你的DBMS的JDBC驱动程序外什么也不需要
当这段代码执行时 数据库的存储过程就被调用 我们没有去获取结果 因为该存储过程并不返回结果 执行成功或失败将通过例外得知 失败可能意味着调用存储过程时的失败(比如提供的一个参数的类型不正确) 或者一个应用程序的失败(比如抛出一个例外指示在poets数据库中并不存在 Dylan Thomas )
结合SQL *** 作与存储过程
映射Java对象到SQL表中的行相当简单 但是通常需要执行几个SQL语句 可能是一个SELECT查找ID 然后一个INSERT插入指定ID的数据 在高度规格化(符合更高的范式 译注)的数据库模式中 可能需要多个表的更新 因此需要更多的语句 Java代码会很快地膨胀 每一个语句的网络开销也迅速增加
将这些SQL语句转移到一个存储过程中将大大简化代码 仅涉及一次网络调用 所有关联的SQL *** 作都可以在数据库内部发生 并且 存储过程语言 例如PL/SQL 允许使用SQL语法 这比Java代码更加自然 下面是我们早期的存储过程 使用Oracle的PL/SQL语言编写
create procedure set_death_age(poet VARCHAR poet_age NUMBER)poet_id NUMBER;beginSELECT id INTO poet_id FROM poets WHERE name = poet;INSERT INTO deaths (mort_id age) VALUES (poet_id poet_age);end set_death_age;
很独特?不 我打赌你一定期待看到一个poets表上的UPDATE 这也暗示了使用存储过程实现是多么容易的一件事情 set_death_age几乎可以肯定是一个很烂的实现 我们应该在poets表中添加一列来存储逝世年龄 Java代码中并不关心数据库模式是怎么实现的 因为它仅调用存储过程 我们以后可以改变数据库模式以提高性能 但是我们不必修改我们代码
下面是调用上面存储过程的Java代码
public static void setDeathAge(Poet dyingBard int age)throws SQLException{ Connection con = null; CallableStatement proc = null;
try {con = connectionPool getConnection();proc = con prepareCall( { call set_death_age( ) } );proc setString( dyingBard getName());proc setInt( age);proc execute(); } finally {try{ proc close();}catch (SQLException e) {}con close(); }}
为了确保可维护性 建议使用像这儿这样的static方法 这也使得调用存储过程的代码集中在一个简单的模版代码中 如果你用到许多存储过程 就会发现仅需要拷贝 粘贴就可以创建新的方法 因为代码的模版化 甚至也可以通过脚本自动生产调用存储过程的代码
Functions
存储过程可以有返回值 所以CallableStatement类有类似getResultSet这样的方法来获取返回值 当存储过程返回一个值时 你必须使用registerOutParameter方法告诉JDBC驱动器该值的SQL类型是什么 你也必须调整存储过程调用来指示该过程返回一个值
下面接着上面的例子 这次我们查询Dylan Thomas逝世时的年龄 这次的存储过程使用PostgreSQL的pl/pgsql
create function snuffed_it_when (VARCHAR) returns integer declarepoet_id NUMBER;poet_age NUMBER;begin first get the id associated with the poet SELECT id INTO poet_id FROM poets WHERE name = $ ; get and return the age SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;return age;end; language pl/pgsql ;
另外 注意pl/pgsql参数名通过Unix和DOS脚本的$n语法引用 同时 也注意嵌入的注释 这是和Java代码相比的另一个优越性 在Java中写这样的注释当然是可以的 但是看起来很凌乱 并且和SQL语句脱节 必须嵌入到Java String中
下面是调用这个存储过程的Java代码
connection setAutoCommit(false);CallableStatement proc =connection prepareCall( { = call snuffed_it_when() } );proc registerOutParameter( Types INTEGER);proc setString( poetName);cs execute();int age = proc getInt( );
如果指定了错误的返回值类型会怎样?那么 当调用存储过程时将抛出一个RuntimeException 正如你在ResultSet *** 作中使用了一个错误的类型所碰到的一样
复杂的返回值
关于存储过程的知识 很多人好像就熟悉我们所讨论的这些 如果这是存储过程的全部功能 那么存储过程就不是其它远程执行机制的替换方案了 存储过程的功能比这强大得多
当你执行一个SQL查询时 DBMS创建一个叫做cursor(游标)的数据库对象 用于在返回结果中迭代每一行 ResultSet是当前时间点的游标的一个表示 这就是为什么没有缓存或者特定数据库的支持 你只能在ResultSet中向前移动
某些DBMS允许从存储过程中返回游标的一个引用 JDBC并不支持这个功能 但是Oracle PostgreSQL和DB 的JDBC驱动器都支持在ResultSet上打开到游标的指针(pointer)
设想列出所有没有活到退休年龄的诗人 下面是完成这个功能的存储过程 返回一个打开的游标 同样也使用PostgreSQL的pl/pgsql语言
create procedure list_early_deaths () return refcursor as declaretoesup refcursor;beginopen toesup forSELECT poets name deaths ageFROM poets deaths all entries in deaths are for poets but the table might bee generic WHERE poets id = deaths mort_idAND deaths age < ;return toesup;end; language plpgsql ;
下面是调用该存储过程的Java方法 将结果输出到PrintWriter
PrintWriter:
static void sendEarlyDeaths(PrintWriter out){ Connection con = null; CallableStatement toesUp = null; try {con = ConnectionPool getConnection();
// PostgreSQL needs a transaction to do this con setAutoCommit(false);
// Setup the call CallableStatement toesUp= connection prepareCall( { = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();
ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){ String name = rs getString( ); int age = rs getInt( ); out println(name + was + age + years old );}rs close(); } catch (SQLException e) {// We should protect these calls toesUp close();con close(); }}
因为JDBC并不直接支持从存储过程中返回游标 我们使用Types OTHER来指示存储过程的返回类型 然后调用getObject()方法并对返回值进行强制类型转换
这个调用存储过程的Java方法是mapping的一个好例子 Mapping是对一个集上的 *** 作进行抽象的方法 不是在这个过程上返回一个集 我们可以把 *** 作传送进去执行 本例中 *** 作就是把ResultSet打印到一个输出流 这是一个值得举例的很常用的例子 下面是调用同一个存储过程的另外一个方法实现
public class ProcessPoetDeaths{ public abstract void sendDeath(String name int age);}
static void mapEarlyDeaths(ProcessPoetDeaths mapper){ Connection con = null; CallableStatement toesUp = null; try {con = ConnectionPool getConnection();con setAutoCommit(false);
CallableStatement toesUp= connection prepareCall( { = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();
ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){ String name = rs getString( ); int age = rs getInt( ); mapper sendDeath(name age);}rs close(); } catch (SQLException e) {// We should protect these calls toesUp close();con close(); }}
这允许在ResultSet数据上执行任意的处理 而不需要改变或者复制获取ResultSet的方法
static void sendEarlyDeaths(final PrintWriter out){ ProcessPoetDeaths myMapper = new ProcessPoetDeaths() {public void sendDeath(String name int age){ out println(name + was + age + years old );} }; mapEarlyDeaths(myMapper);}
这个方法使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths 该实例拥有sendDeath方法的一个实现 和我们上面的例子一样的方式把结果写入到输出流 当然 这个技巧并不是存储过程特有的 但是和存储过程中返回的ResultSet结合使用 是一个非常强大的工具
结论
存储过程可以帮助你在代码中分离逻辑 这基本上总是有益的 这个分离的好处有
快速创建应用 使用和应用一起改变和改善的数据库模式
数据库模式可以在以后改变而不影响Java对象 当我们完成应用后 可以重新设计更好的模式
存储过程通过更好的SQL嵌入使得复杂的SQL更容易理解
编写存储过程比在Java中编写嵌入的SQL拥有更好的工具——大部分编辑器都提供语法高亮!
存储过程可以在任何SQL命令行中测试 这使得调试更加容易
并不是所有的数据库都支持存储过程 但是存在许多很棒的实现 包括免费/开源的和非免费的 所以移植并不是一个问题 Oracle PostgreSQL和DB 都有类似的存储过程语言 并且有在线的社区很好地支持
存储过程工具很多 有像TOAD或TORA这样的编辑器 调试器和IDE 提供了编写 维护PL/SQL或pl/pgsql的强大的环境
lishixinzhi/Article/program/Java/hx/201311/25906
什么》? 哎呀没必要。。
不过可实现的:如下为一个通用的例子:
假设有这么个对象:
import javaioSerializable;
public class MyObject implements Serializable {
private static final long serialVersionUID = 1L;
private int i;
public int getI() {
return i;
}
public void setI(int i) {
thisi = i;
}
}
//测试 的方法如下
import javaioByteArrayInputStream;
import javaioByteArrayOutputStream;
import javaioIOException;
import javaioObjectInputStream;
import javaioObjectOutputStream;
import javasqlConnection;
import javasqlDriverManager;
import javasqlPreparedStatement;
import javasqlResultSet;
public class test {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
MyObject obj = new MyObject();
objsetI(4567);
write(Object2Bytes(obj));
// read();
}
public static void write(byte[] b) throws ClassNotFoundException {
Systemoutprintln(blength);
ClassforName("sunjdbcodbcJdbcOdbcDriver");
try {
Connection con = DriverManagergetConnection("jdbc:odbc:temp");
String sql = "insert into tab values()";
PreparedStatement pstmt = conprepareStatement(sql);
pstmtsetBytes(1, b);
pstmtexecute();
pstmtclose();
conclose();
} catch (Exception e) {
eprintStackTrace();
}
}
public static void read() throws ClassNotFoundException {
ClassforName("sunjdbcodbcJdbcOdbcDriver");
try {
Connection con = DriverManagergetConnection("jdbc:odbc:temp");
String sql = "select from tab";
PreparedStatement pstmt = conprepareStatement(sql);
ResultSet res = pstmtexecuteQuery();
while (res != null && resnext()) {
byte[] b = resgetBytes("key");
Systemoutprintln(blength);
MyObject obj = (MyObject) Bytes2Object(b);
Systemoutprintln(objgetI());
}
pstmtclose();
conclose();
} catch (Exception e) {
eprintStackTrace();
}
}
// 将对象转换成字节数组
public static byte[] Object2Bytes(Object obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
ooswriteObject(obj);
return baostoByteArray();
}
// 将字节数组转换成为对象
public static Object Bytes2Object(byte[] b) throws IOException,
ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(b);
ObjectInputStream ois = new ObjectInputStream(bais);
Object obj = oisreadObject();
return obj;
}
}
SQPte 一个非常流行的嵌入式数据库,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。此外它还是开源的,任何人都可以使用它。许多开源项目((Mozilla, PHP, Python)都使用了 SQPte SQPte 由以下几个组件组成:SQL 编译器、内核、后端以及附件。SQPte 通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展 SQPte 的内核变得更加方便。 图 1 SQPte 内部结构 SQPte 基本上符合 SQL-92 标准,和其他的主要 SQL 数据库没什么区别。它的优点就是高效,Android 运行时环境包含了完整的 SQPte。 SQPte 和其他数据库最大的不同就是对数据类型的支持,创建一个表时,可以在 CREATE TABLE 语句中指定某列的数据类型,但是你可以把任何数据类型放入任何列中。当某个值插入数据库时,SQPte 将检查它的类型。如果该类型与关联的列不匹配,则 SQPte 会尝试将该值转换成该列的类型。如果不能转换,则该值将作为其本身具有的类型存储。比如可以把一个字符串(String)放入 INTEGER 列。SQPte 称这为“弱类型”(manifest typing)。 此外,SQPte 不支持一些标准的 SQL 功能,特别是外键约束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FPL OUTER JOIN, 还有一些 ALTER TABLE 功能。 除了上述功能外,SQPte 是一个完整的 SQL 系统,拥有完整的触发器,交易等等。 Android 集成了 SQPte 数据库 Android 在运行时(run-time)集成了 SQPte,所以每个 Android 应用程序都可以使用 SQPte 数据库。对于熟悉 SQL 的开发人员来时,在 Android 开发中使用 SQPte 相当简单。但是,由于 JDBC 会消耗太多的系统资源,所以 JDBC 对于手机这种内存受限设备来说并不合适。因此,Android 提供了一些新的 API 来使用 SQPte 数据库,Android 开发中,程序员需要学使用这些 API。 数据库存储在 data/< 项目文件夹 >/databases/ 下。 Android 开发中使用 SQPte 数据库 Activites 可以通过 Content Provider 或者 Service 访问一个数据库。下面会详细讲解如果创建数据库,添加数据和查询数据库。 创建数据库 Android 不自动提供数据库。在 Android 应用程序中使用 SQPte,必须自己创建数据库,然后创建表、索引,填充数据。Android 提供了 SQPteOpenHelper 帮助你创建一个数据库,你只要继承 SQPteOpenHelper 类,就可以轻松的创建数据库。SQPteOpenHelper 类根据开发应用程序的需要,封装了创建和更新数据库使用的逻辑。SQPteOpenHelper 的子类,至少需要实现三个方法: 构造函数,调用父类 SQPteOpenHelper 的构造函数。这个方法需要四个参数:上下文环境(例如,一个 Activity),数据库名字,一个可选的游标工厂(通常是 NPl),一个代表你正在使用的数据库模型版本的整数。 onCreate()方法,它需要一个 SQPteDatabase 对象作为参数,根据需要对这个对象填充表和初始化数据。 onUpgrage() 方法,它需要三个参数,一个 SQPteDatabase 对象,一个旧的版本号和一个新的版本号,这样你就可以清楚如何把一个数据库从旧的模型转变到新的模型。 下面示例代码展示了如何继承 SQPteOpenHelper 创建数据库: pubPc class DatabaseHelper extends SQPteOpenHelper { DatabaseHelper(Context context, String name, CursorFactory cursorFactory, int version) { super(context, name, cursorFactory, version); } @Override pubPc void onCreate(SQPteDatabase db) { // TODO 创建数据库后,对数据库的 *** 作 } @Override pubPc void onUpgrade(SQPteDatabase db, int PdVersion, int newVersion) { // TODO 更改数据库版本的 *** 作 } @Override pubPc void onOpen(SQPteDatabase db) { superonOpen(db); // TODO 每次成功打开数据库后首先被执行 } } 接下来讨论具体如何创建表、插入数据、删除表等等。调用 getReadableDatabase() 或 getWriteableDatabase() 方法,你可以得到 SQPteDatabase 实例,具体调用那个方法,取决于你是否需要改变数据库的内容: db=(new DatabaseHelper(getContext()))getWritableDatabase(); return (db == nPl) false : true; 上面这段代码会返回一个 SQPteDatabase 类的实例,使用这个对象,你就可以查询或者修改数据库。 当你完成了对数据库的 *** 作(例如你的 Activity 已经关闭),需要调用 SQPteDatabase 的 Close() 方法来释放掉数据库连接。 创建表和索引 为了创建表和索引,需要调用 SQPteDatabase 的 execSQL() 方法来执行 DDL 语句。如果没有异常,这个方法没有返回值。 例如,你可以执行如下代码: dbexecSQL("CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, value REAL);"); 这条语句会创建一个名为 mytable 的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数(例如,当你插入一行时,SQPte 会给这列自动赋值),另外还有两列:title( 字符 ) 和 value( 浮点数 )。 SQPte 会自动为主键列创建索引。 通常情况下,第一次创建数据库时创建了表和索引。如果你不需要改变表的 schema,不需要删除表和索引 删除表和索引,需要使用 execSQL() 方法调用 DROP INDEX 和 DROP TABLE 语句。 给表添加数据 上面的代码,已经创建了数据库和表,现在需要给表添加数据。有两种方法可以给表添加数据。 像上面创建表一样,你可以使用 execSQL() 方法执行 INSERT, UPDATE, DELETE 等语句来更新表的数据。execSQL() 方法适用于所有不返回结果的 SQL 语句。例如: dbexecSQL("INSERT INTO widgets (name, inventory)"+ "VALUES ('Sprocket', 5)"); 另一种方法是使用 SQPteDatabase 对象的 insert(), update(), delete() 方法。这些方法把 SQL 语句的一部分作为参数。示例如下: ContentValues cv=new ContentValues(); cvput(ConstantsTITLE, "example title"); cvput(ConstantsVALUE, SensorManagerGRAVITY_DEATH_STAR_I); dbinsert("mytable", getNPlCPumnHack(), cv); update()方法有四个参数,分别是表名,表示列名和值的 ContentValues 对象,可选的 WHERE 条件和可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记。update() 根据条件,更新指定列的值,所以用 execSQL() 方法可以达到同样的目的。 WHERE 条件和其参数和用过的其他 SQL APIs 类似。例如: String[] parms=new String[] {"this is a string"}; dbupdate("widgets", replacements, "name=", parms); delete() 方法的使用和 update() 类似,使用表名,可选的 WHERE 条件和相应的填充 WHERE 条件的字符串。 查询数据库 类似 INSERT, UPDATE, DELETE,有两种方法使用 SELECT 从 SQPte 数据库检索数据。 1 .使用 rawQuery() 直接调用 SELECT 语句; 使用 query() 方法构建一个查询。 Raw Queries正如 API 名字,rawQuery() 是最简单的解决方法。通过这个方法你就可以调用 SQL SELECT 语句。例如: Cursor c=dbrawQuery( "SELECT name FROM sqPte_master WHERE type='table' AND name='mytable'", nPl); 在上面例子中,我们查询 SQPte 系统表(sqPte_master)检查 table 表是否存在。返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。如果查询是动态的,使用这个方法就会非常复杂。例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。 RegPar Queriesquery() 方法用 SELECT 语句段构建查询。SELECT 语句内容作为 query() 方法的参数,比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP BY 条件,HAVING 条件。除了表名,其他参数可以是 nPl。所以,以前的代码段可以可写成: String[] cPumns={"ID", "inventory"}; String[] parms={"snicklefritz"}; Cursor resPt=dbquery("widgets", cPumns, "name=",parms, nPl, nPl, nPl); 使用游标不管你如何执行查询,都会返回一个 Cursor,这是 Android 的 SQPte 数据库游标,使用游标,你可以:通过使用 getCount() 方法得到结果集中有多少记录;通过 moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍历所有记录;通过 getCPumnNames() 得到字段名;通过 getCPumnIndex() 转换成字段号;通过 getString(),getInt() 等方法得到给定字段当前记录的值;通过 requery() 方法重新执行查询得到游标;通过 close() 方法释放游标资源;例如,下面代码遍历 mytable 表 Cursor resPt=dbrawQuery("SELECT ID, name, inventory FROM mytable"); resPtmoveToFirst(); while (!resPtisAfterLast()) { int id=resPtgetInt(0); String name=resPtgetString(1); int inventory=resPtgetInt(2); // do something usefP with these resPtmoveToNext(); } resPtclose(); 在 Android 中使用 SQPte 数据库管理工具 在其他数据库上作开发,一般都使用工具来检查和处理数据库的内容,而不是仅仅使用数据库的 API。使用 Android 模拟器,有两种可供选择的方法来管理数据库。首先,模拟器绑定了 sqPte3 控制台程序,可以使用 adb shell 命令来调用他。只要你进入了模拟器的 shell,在数据库的路径执行 sqPte3 命令就可以了。数据库文件一般存放 在:/data/data/yourapppackage/databases/your-db-name如果你喜欢使用更友好的工具,你 可以把数据库拷贝到你的开发机上,使用 SQPte-aware 客户端来 *** 作它。这样的话,你在一个数据库的拷贝上 *** 作,如果你想要你的修改能反映到设备上,你需要把数据库备份回去。把数据库从设备上考出来,你可以使 用 adb pPl 命令(或者在 IDE 上做相应 *** 作)。存储一个修改过的数据库到设备上,使用 adb push 命令。一个最方便的 SQPte 客户端是 FireFox SQPte Manager 扩展,它可以跨所有平台使用。 图 2 SQPte Manager 结束语 如果你想要开发 Android 应用程序,一定需要在 Android 上存储数据,使用 SQPte 数据库是一种非常好的选择。本文介绍了如何在 Android 应用程序中使用 SQPte 数据库 ,主要介绍了在 Android 应用程序中使用 SQPte 创建数据库和表、添加数据、更新和检索数据,还介绍了比较常用的 SQPte 管理工具,通过阅读本文,你可以在 Android 中轻松 *** 作 SQPte 数据库。
本文Python *** 作 MySQL 数据库需要是使用到 PyMySQL 驱动
Python *** 作 MySQL 前提是要安装好 MySQL 数据库并能正常连接使用,安装步骤详见下文。
注意: 安装过程我们需要通过开启管理员权限来安装,否则会由于权限不足导致无法安装。
首先需要先下载 MySQL 安装包, 官网下载地址 下载对应版本即可,或直接在网上拉取并安装:
权限设置:
初始化 MySQL:
启动 MySQL:
查看 MySQL 运行状态:
Mysql安装成功后,默认的root用户密码为空,你可以使用以下命令来创建root用户的密码:
登陆:
创建数据库:
查看数据库:
PyMySQL 模块使用 pip命令进行安装:
假如系统不支持 pip 命令,可以使用以下方式安装:
pymysql connect 函数:连接上数据库
输出结果显示如下:表面数据库连接成功
使用 pymysql 的 connect() 方法连接数据库,connect 参数解释如下:
conncursor():获取游标
如果要 *** 作数据库,光连接数据是不够的,咱们必须拿到 *** 作数据库的游标,才能进行后续的 *** 作,游标的主要作用是用来接收数据库 *** 作后的返回结果,比如读取数据、添加数据。通过获取到的数据库连接实例 conn 下的 cursor() 方法来创建游标,实例如下:
输出结果为:
cursor 返回一个游标实例对象,其中包含了很多 *** 作数据的方法,如执行sql语句,sql 执行命令: execute() 和 executemany()
execute(query,args=None):
executemany(query,args=None):
其他游标对象如下表:
完整数据库连接 *** 作实例如下:
以上结果输出为:
创建表代码如下:
如下所示数据库表创建成功:
插入数据实现代码:
插入数据结果:
Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。
查询数据代码如下:
输出结果:
DB API中定义了一些数据库 *** 作的错误及异常,下表列出了这些错误和异常:
本文给大家介绍 Python 如何连接 Mysql 进行数据的增删改查 *** 作,文章通过简洁的代码方式进行示例演示,给使用 Python *** 作 Mysql 的工程师提供支撑。
SQL SERVER 数据库应用技术第二版(张浦生主编)课后习题答案,谁有急求!
浏览次数:29次悬赏分:0 | 离问题结束还有 12 小时 | 提问者:普罗旺斯987 | 检举
还能输入 9999 字
插入插入地图
参考资料:
提交回答
回答 共2条
自己做吧
追问
可是不会呢
回答
问我呀
追问
你会啊,告诉我吧,千恩万谢
回答者: sytdeedee | 六级 | 2011-6-14 13:25 | 检举
凌吧!不给人积分就想要答案 啊
追问
你是谁啊
我用的数据库是sql server 2008 ,用法如下
1。创建数据库
在SQL Server 2008中创建数据库的方法主要有两种:一是在SQL Server Management Studio窗口中使用现有命令和功能,通过方便的图形化向导创建;二是通过编写Transact-SQL语句创建。
例子:
CREATE DATABASE BookDateBase
ON
(
NAME=BookDateBase_DAT,
FILENAME='E:\张帅\zs SQL2008 shugao\SQL2008\第3章 管理数据库 代码\BookDateBase_DATmdf',
SIZE=3MB,
MAXSIZE=50MB,
FILEGROWTH=10%
)
LOG ON
(
NAME=BookDateBase_LOG,
FILENAME='E:\张帅\zs SQL2008 shugao\SQL2008\第3章 管理数据库 代码\BookDateBase_LOGldf',
SIZE=1MB,
MAXSIZE=10MB,
FILEGROWTH=10%
)
GO
2。创建数据表
通过上面对数据表的概述,相信多数用户应该清楚,表是SQL Server中一种重要的数据库对象,它存储了数据库中的所有数据。本节开始,我们就要讲述数据表的创建和常规 *** 作方法,例如,修改表、添加列、修改列等。
例子
USE 电子书查询系统
GO
CREATE TABLE 电子书内容信息
(
序号 int NOT NULL,
关键字段 char(10) NULL,
详细内容 varchar(MAX) NULL,
单条记录int NULL,
单价money NULL,
)
3 数据表的查询、更新、删除和插入 *** 作
(1)查询表
SELECT语句是数据库最基本的语句之一,同时也是SQL编程技术最常用的语句。使用SELECT语句不但可以在数据库中精确地查找某条信息,而且还可以模糊地查找带有某项特征的多条数据。这在很大程度上方便了用户查找数据信息。
例子:
USE 网店购物系统
SELECT 会员编号,会员名称, 消费总额,历史记录 FROM 注册会员
WHERE 会员地址 LIKE '上海%'
(2)更新表
UPDATE语句和大多数SQL语句一样,顾名思义,即更新已有数据。如果关系表中的数据已经没用了,或插入的数据不正确,那么可以修改这些有问题的数据。修改关系中的数据需要使用UPDATE语句。
例子:
update 商品信息
set 库存量=库存量-1
where 商品编号='A10001'
select from 商品信息
go
(3)插入数据
语句是SQL语句中最常用的用于向数据表中插入数据的方法,使用INSERTINSERT语句可向表中添加一个或多个新行
例子
USE 网店购物系统
INSERT INTO 商品信息 VALUES('1000000521','华硕电脑U20A','2000','10')
(4)删除数据
当数据库的添加工作完成以后,随着使用和对数据的修改,表中可能存在一些无用的数据,这些无用的数据不仅会占用空间,还会影响修改和查询的速度,所以应及时将它们删除。
例子
use 购物系统
go
DELETE FROM 商品信息 where 商品名称 like '%苹果%'
Go
3 存储过程
(1)创建存储过程
在SQL Server 2008 ,可以使用T-SQL语句CREATE PROCEDURE来创建存储过程。在创建存储过程时,应该指定所有的输入参数、执行数据库 *** 作的编程语句、返回至调用过程或批处理时以示成功或失败的状态值、捕获和处理潜在错误时的错误处理语句等。
例子
在SQL Server 2008的示例数据库BookDatebase中创建一个名为Reader_proc的存储过程,它将从表中返回所有读者的姓名、姓别、电话、等级。使用CREATE PROCEDURE语句如下:
Use BookDatebase
Go
CREATE PROCEDURE Reader_proc
As
SELECT Rname,Rsex,Rphone,rleve
FROM Reader
(2)使用存储过程
在需要执行存储过程时,可以使用T-SQL语句EXECUTE。
例子
Use BookDatebase
Go
EXECUTE Reader_proc
4 触发器
(1)INSERT触发器
INSERT触发器就是当对目标表(触发器的基表)执行INSERT语句时,就会调用的触发器。
例子:
create TRIGGER BookClassCounts
ON [dbo][Books]
AFTER insert
AS
select count(BbigClass) as '类别'
from Books B,inserted i
where BbigClass=ibigClass
(2)UPDATE触发器
更新触发器是当一个UPDATE语句在目标表上运行的时候,就调用更新触发器。就像任何其他触发器一样,当调用触发器,就运行被触发的SQL语句并且发生动作。
例子
create TRIGGER [dbo][BooksBnumUpdate] / 当书号改变时/
ON [dbo][Books]
AFTER UPDATE
AS
if UPDATE(Bnum)
BEGIN
update BorrowORreturn
set BorrowORreturnBnum=iBnum
from BorrowORreturn B,inserted i,deleted d
where BBnum=dBnum
END
(3)DELETE触发器
当触发DELETE触发器时,从受影响的表中删除的行将被放置到一个特殊的DELETE表中。DELETE表跟INSERTED表一样也是一个临时表,它保留已被删除数据行的一个副本。
create TRIGGER [dbo][ReaderDelete]
ON [dbo][Reader]
AFTER DELETE
AS
delete BorrowORreturn
from BorrowORreturn b,deleted d
where bRcert=dRcert
有了这些基本上已经够你用了,如果你都学会了,就成数据库高手了
为了写这些用了老大功夫,不给分不行哦
以上就是关于Java数据库程序中的存储过程设计全部的内容,包括:Java数据库程序中的存储过程设计、关于数据库保存流java流对象、安卓怎么使用sqlite数据库实例等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)