基于web的二手书交易管理系统的设计与实现外文翻译资料

 2022-11-06 15:57:57

文献来源:AbrahamSilberschatz, HenryF.Korth, S.Sudarshan,等. 数据库系统概念[M]. 高等教育出版社, 2014.

Advanced SQL

In Chapters 3 and 4, we provided detailed coverage of the basic structure of SQL. In this chapter, we cover some of the more advanced features of SQL.1 We address the issue of how to access SQL from a general-purpose programming language, which is very important for building applications that use a database to store and retrieve data. We describe how procedural code can be executed within the database, either by extending the SQL language to support procedural actions, or by allowing functions defined in procedural languages to be executed within the database. We describe triggers, which can be used to specify actions that are to be carried out automatically on certain events such as insertion, deletion, or update of tuples in a specified relation. We discuss recursive queries and advanced aggregation features supported by SQL. Finally, we describe online analytic processing (OLAP) systems, which support interactive analysis of very large datasets.

5.1 Accessing SQL From a Programming Language

SQL provides a powerful declarative query language. Writing queries in SQL is usually much easier than coding the same queries in a general-purpose programming language. However, a database programmer must have access to a general-purpose programming language for at least two reasons:

1. Not all queries can be expressed in SQL, since SQL does not provide the full expressive power of a general-purpose language. That is, there exist queries that can be expressed in a language such as C, Java, or Cobol that cannot be expressed in SQL. To write such queries, we can embed SQL within a more powerful language.

2. Nondeclarative actions—such as printing a report, interacting with a user, or sending the results of a query to a graphical user interface—cannot be done from within SQL. Applications usually have several components, and querying or updating data is only one component; other components are written in general-purpose programming languages. For an integrated

application, there must be a means to combine SQL with a general-purpose programming language.

There are two approaches to accessing SQL from a general-purpose programming

language:

bull; Dynamic SQL: A general-purpose program can connect to and communicate with a database server using a collection of functions (for procedural languages) or methods (for object-oriented languages). Dynamic SQL allows the program to construct an SQL query as a character string at runtime, submit the query, and then retrieve the result into program variables a tuple at a time. The dynamic SQL component of SQL allows programs to construct and submit SQL queries at runtime. In this chapter, we look at two standards for connecting to an SQL database and performing queries and updates. One, JDBC (Section 5.1.1), is an application program interface for the Java language. The other, ODBC (Section 5.1.2), is an application program interface originally developed for the C language, and subsequently extended to other languages such as C , C#, and Visual Basic.

bull; Embedded SQL: Like dynamic SQL, embedded SQL provides a means by which a program can interact with a database server. However, under embedded SQL, the SQL statements are identified at compile time using a preprocessor. The preprocessor submits the SQL statements to the database system for precompilation and optimization; then it replaces the SQL statements in the application program with appropriate code and function calls before invoking the programming-language compiler. Section 5.1.3 covers embedded SQL.

A major challenge in mixing SQL with a general-purpose language is the mismatch in the ways these languages manipulate data. In SQL, the primary type of data is the relation. SQL statements operate on relations and return relations as a result. Programming languages normally operate on a variable at a time, and those variables correspond roughly to the value of an attribute in a tuple in a relation. Thus, integrating these two types of languages into a single application requires providing a mechanism to return the result of a query in a manner that the program can handle.

5.1.1 JDBC

The JDBC standard defines an application program interface (API) that Java programs can use to connect to database servers. (The word JDBC was originally an abbreviation for Java Database Connectivity, but the full form is no longer used.)

Figure 5.1 shows an example Java program that uses the JDBC interface. It illustrates how connections are opened, how statements are executed and results processed, and how connections are closed. We discuss this example in detail in this section. The Java program must import java.sql.*, which contains the interface definitions for the functionality provided by JDBC.

5.1.1.1 Connecting to the Database

The first step in accessing a database from a Java program is to open a connection to the database. This step is required to select which database to use, for example, an instance of Oracle running on your machine, or a PostgreSQL database running on another machine. Only after opening a connection can a Java program execute SQL statements.

A connection is opened using the getConnection method of the Driver-Manager class (within java.sql). This method takes three parameters.

bull; The first parameter to the getConnection call is a string that specifies the URL, or machine name, where the server runs (in our example, db.yale.edu), along with possibly some other information such as the protocol to be used to communicate with the database (in our example, jdbc:oracle:thin:;we shall shortly see why this is required), the port number the database system uses for communication (in our example, 2000), and the specific database on the server to be used (in our example, univdb). Note that JDBC specifi

剩余内容已隐藏,支付完成后下载完整资料


高级SQL

在第3章和第4章我们详细地介绍了SQL的基本结构。在本章中我们将介绍SQL的一些高级特性。本章首先介绍如何使用通用程序设计语言来访问SQL,这对于构建用数据库存取数据的应用有重要意义。我们将介绍两种在数据库中执行设计语言代码的方法:一种是通过扩展SQL语言来支持程序的操作;另一种是在数据库中执行程序语言中定义的函数。接下来本章将介绍触发器,用于说明当特定时间(例如在某个表上进行元组插入、删除或更新操作)发生时自动执行的操作。然后本章将讨论递归查询和SQL支持的高级聚集特性。最后我们将对联机分析处理系统加以介绍,它可用于海量数据的交互分析。

5.1 使用程序设计语言访问数据库

SQL提供了一种强大的声明性查询语言。实现相同的查询,用SQL写查询语句比用通用程序设计语言要简单得多。然而,数据库程序员必须能够使用通用程序设计语言,原因至少有以下两点:

1,因为SQL没有提供通用程序设计语言那样得表达能力,所以SQL并不能表达所有查询要求。也就是说,有可能存在这样得查询,可以用C、Java或Cobol编写,而用SQL做不到。要写这样得查询,我们可以将SQL嵌入到一种更强大的语言中。

 2,非声明性的动作(例如打印一份报告、和用户交互,或者把一次查询的结果送到一个图形用户界面中)都不能用SQL实现。一个应用程序通常包括很多部分,查询或更新数据只是其中之一,而其他部分则用通用程序设计语言实现。对于集成应用来说,必须用某种方法把SQL与通用编程语言结合起来。

可以通过以下两种方法从通用编程语言中访问SQL:

1,动态SQL:通用程序设计语言可以通过函数(对于过程式语言)或者方法(对于面向对象的语言)来连接数据库服务器并与之交互。利用动态SQL可以在运行在运行时以字符串形式构建SQL查询,提交查询,然后把结果存入程序变量中,每次一个元组。动态SQL的SQL组件允许程序在运行时构建和提交SQL查询。

在这一章中,我们将介绍两种用于连接到SQL数据库并执行查询和更新的标准。一种时Java语言的应用程序结构JDBC。另一种是ODBC,它最初时为C语言开发的,后来扩展到其他语言如C 、C#和Visual Basic。

2,嵌入式SQL:与动态SQL类似,嵌入式SQL提供了另外一种使程序与数据库服务器交互的手段。然而,嵌入式SQL语句必须在编译时全部确定,并交给预处理器。预处理程序提交SQL语句到数据库系统进行预编译和优化,然后它把应用程序中的SQL语句替换成相应的代码和函数,最后调用程序语言的编译器进行编译。5.1.3节涵盖嵌入式SQL的内容。

把SQL与通用程序语言相结合的主要挑战是:这些语言处理数据的方式互不兼容。在SQL中,数据的主要类型是关系。SQL语句在关系上进行操作,并返回关系作为结果。程序设计语言通常一次操作一个变量,这些变量大致相当于关系中一个元组的一个属性的值。因此,为了在同一个应用中整合这两类语言,必须提供一种转换机制,使得程序语言可以处理查询的返回结果。

5.1.1 JDBC

JDBC标准定义了Java程序连接数据库服务器的应用程序接口。图5.1给出了一个利用JDBC接口的Java程序的例子。它向我们演示了如何打开数据库连接,执行语句,处理语句,最后关闭连接。我们将在本节详细讨论这个实例。注意,Java程序必须引用java.sql.*,它包含了JDBC所提供功能的接口定义。

5.1.1连接到数据库

要在java程序中访问数据库,首先要打开一个数据库连接。这一步需要选择使用哪个数据库。例如,可以是你机器上的一个oracle实例,也可以是运行在另一台机器上的一个postgreSQL数据库。只有在打开数据库连接以后,Java程序才能执行SQL语句。

可以通过调用DriverManger类的getConnection方法来打开一个数据库连接。该方法有三个参数。

GetConnection方法的第一个参数是以字符串类型表示的URL,指明服务器所在的主机名称(在我们的例子里是db.yale.edu)以及可能包含的其他信息。例如,与数据库通信所用的协议,数据库系统用来通信的端口号,还有服务器端使用的特定数据库。注意JDBC只是指定API而不指定通信协议。一个JDBC驱动器可能支持多种协议。我们必须指定一个数据库和驱动器都支持的协议。协议的详细内容是由提供商设定的。

GetConnection 方法的第二个参数用于指定一个数据库用户标识,它为字符串类型。

第三个参数是密码,它也是字符串类型。(注意,把密码直接写在JDBC代码中会增加安全性隐患,因为你的代码有可能会被某些未被授权的用户所访问。)

在图5-1中的例子中,我们已经建立了一个Connection对象,其句柄是conn。

每个支持JDBC(大多数的数据库提供商都支持)的数据库产品都会提供一个JDBC驱动程序(JDBCdriver),该驱动程序必须被动态加载才能实现java对数据库的访问。事实上,必须在连接数据库之前完成驱动程序的加载。

在图5-1中程序的第一行调用Class.forName函数完成驱动程序的加载,在调用时需要通过参数来指定一个实现了java.sql.Driver接口的实体类。这个接口的功能是为了实现不同层面的操作之间的转换,一边是与产品类型无关的JDBC操作,另一边是与产品相关的,在所使用的特定数据库管理系统中完成的操作。图中的实例采用了oracle的驱动程序,oracle.jabc.driver.OracleDriver.该驱动程序包含在一个.jar文件里,可以从提供商的网站下载,然后放在java的类路径里,用于java编译器访问。

用来于数据库交换信息的具体协议并没有在JDBC标准中定义,而是由所使用的驱动程序决定的。有些驱动程序支持多种协议,使用哪一种更合适取决于所连接的数据库支持什么协议。我们的例子里在打开一个数据库连接时,字符串jdbc:oracle:thin:指定了Oracle支持的一个特定协议。

5.1.1.2 向数据库系统中传递SQL语句

一旦打开了一个数据库连接,程序就可以利用该连接来向数据库发送SQL语言用来执行。这是通过Statement类的一个实例来完成的。一个Statement对象并不代表SQL语句本身,而是实现了可以被Java程序调用的一些方法,通过参数来传递SQL语句并被数据库系统所执行。我们的例子在连接变量coon上创建了一个Statement句柄。

我们既可以用使用executeQuery函数又可以用executeUpdate函数来执行一条语句,这取决于这条SQL语句是查询语句(如果是查询语句,自然会返回一个结果集),还是像更新、插入、删除、创建表等这样的非查询性语句。在我们的例子里,stmt. executeUpdate执行了一条更新语句,向instructor关系中插入数据。它返回一个整数。表示被插入、更新或者删除的元组个数。对于DDL语句,返回值是0.try catch结构让我们可以捕捉JDBC产生的异常,并显示给用户适当的出错信息。

5.1.1.3 获取查询结果

示例程序用stmt. executeUpdate来执行一次查询。它可以把结果中的元组集合提取到ResultSet对象变量rest中并每次取出一个进行处理。结果集的next方法用来查看在集合中是否还存在至少一个尚未取回的元组,如果存在的话就取出。Next方法的返回值是一个布尔变量,表示是否从结果集中取回了一个元组。可以通过一系列的名字以get为前缀的方法来得到所获取元组的各个属性。方法getstring可以返回所有的基本SQL数据类型的属性(被转换成Java中的String类型的值),当然也可以使用像getFloat那样一些约束性更强的方法。这些不同的get方法的参数既可以是一个字符串类型的属性名称,又可以是一个整数,用来表示所需获取的属性在元组中的位置。图5-1给出了两种在元组中提取属性值的办法:利用属性名提取或者利用属性位置提取。

Java程序结束的时候语句和连接都将被关闭。注意关闭连接是很重要的,因为数据库连接的个数是有限制的:未关闭的连接可能导致超过这一限制。如果发生这种情况,应用将不能再打开任何数据库连接。

5.1.1.1预备语句

我们也可以通过以“?”来代表以后再给出的实际值,而创建一个预备语句。数据库系统在准备了查询语句的时候对它进行编译。在每次执行该语句时(用新值替换“?”),数据库可以重用预先编译的查询的形式,应用新值进行查询。图5-2的代码框架给出了如何使用预备语句的示例。

可以使用Connection类的prepareStatement方法来提交SQL语句用于编译。它返回一个prepared Statement类的对象。此时还没有执行SQL语句。执行需要PrepareStatement类的方法来为“?”参数设定具体的值。SetString方法以及诸如setlnt等用于其他的SQL基本类型的其他类似的方法使我们能够为参数指定值。第一个参数用来确定我们为哪个“?”设定值。第二个参数是我们要设定的值。

在图5-2中的例子里,我们预备了一个insert语句,设定“?”参数,并且调用executeUpdate。例子中的最后两行显示,参数设定保持不变,直到我们特别地进行重新设定。这样,最后地语句调用executeUpdate,元组被插入到数据库。

在同一查询编译一次然后设置不同地参数值执行多次的情况下,预备语句使得执行更加高效。然而,预备语句有一个更加重要的优势,它使得只要使用了用户输入值,即使只运行一次,预备语句都是执行SQL查询的首选方法。假设我们读取了一个用户输入值,然后使用java的字符串操作来构造SQL语句。如果用户输入了某些特殊字符,例如一个单引号,除非我们采用额外工作对用户输入进行检查,否则生成的SQL语句会出现语法错误。Set string方法为我们自动完成检查,并插入需要的转义字符,以确保语法的正确性。

在我们的例子中,假设用户已经输入了ID, name, dept name,和salary这些变量的值,相应的元组将被插入到关系instructor中。假设我们不用预备语句,而是使用如下的java表达式把字符串连接起来构成查询:

'insert into instructor values(rsquo; ' ID ' rsquo;, rsquo; ' name ' rsquo;, ' ' rsquo; dept name ' rsquo;, ' rsquo; balance ')'

并且查询通过Statement对象的executeQuery方法被直接执行。现在,如果用户在ID或者name中敲入一个单引号,查询语句就会出现语法错误。一个教员的名字有可能带有引号(例如“Orsquo;Henry”)

也许以上的例子会被认为是一个小问题,而某些情况会比这糟糕的多。一种叫做SQL注入的技术可以被恶意黑客用来切取数据和损坏数据库。

假设一个java程序输入一个字符串name,并且构建下面的查询:'select * from instructor where name = rsquo;' name 'rsquo;'

如果用户没有输入一个名字,而是输入:Xrsquo; or rsquo;Yrsquo; = rsquo;Y,这样产生的语句就变成'select * from instructor where name = rsquo;' 'Xrsquo; or rsquo;Yrsquo; = rsquo;Y' 'rsquo;',即select * from instructor where name = rsquo;Xrsquo; or rsquo;Yrsquo; = rsquo;Yrsquo;,在生成的查询中,where子句总是真,所以查询结果返回整个instructor关系。更诡计多端的恶意用户甚至可以编写输入值以输出更多的数据。使用预备语句就可以防止这类问题,因为输入的字符串将被插入转义符,因此最后的查询变为:'select * from instructor where name = rsquo;Xrsquo; or rsquo;Yrsquo; = rsquo;Yrsquo;,这是无害的查询语句,返回结果为空集。

比较老的系统允许多个由分号隔开的语句在一次调用里被执行。此功能正逐渐被淘汰,因为恶意的黑客会利用SQL注入技术插入整个SQL语句。由于这些语句在java程序所有者的权限上运行,像删除表这样毁灭性的SQL语句会被执行。SQL应用程序开发者必须警惕这种潜在的安全漏洞。

5.1.1.5 可调用语句

JDBC还提供了CallableStatement接口来允许调用SQL的存储过程和函数,此接口对函数和过程所扮演的角色跟preparestatement对查询所扮演的角色一样。

CallableStatement cStmt1 = conn.prepareCall('{? = call some function(?)}');

CallableStatement cStmt2 = conn.prepareCall('{call some procedure(?,?)}');

函数返回值和过程的对外参数的数据类型必须先用方法registerOutParameter()注册,它们可以用与结果集用的方法类似的get方法获取。请参看JDBC手册以获得更细节的信息。

5.1.1.6 元数据特性

正如我们此前提到的,一个java应用程序不包含数据库中存储的数据的声明。这些声明是SQL数据定义语言的一部分,因此,使用JDBC的java程序必须要么将关于数据库模式的假设硬编码到程序中,要么直接在运行时从数据库系统中得到那些信息。后一种方法更可取,因为它使得应用程序可以更健壮地处理数据库模式地变化。

回想一下,当我们提交一个使用executeQuery方法地查询时,查询结果被封装在一

剩余内容已隐藏,支付完成后下载完整资料


资料编号:[139149],资料为PDF文档或Word文档,PDF文档可免费转换为Word

您需要先支付 30元 才能查看全部内容!立即支付

课题毕业论文、外文翻译、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。