posts - 5,  comments - 0,  trackbacks - 0
           

          一.JDBC原理概述

          1JDBC是一套協(xié)議,是JAVA開(kāi)發(fā)人員和數(shù)據(jù)庫(kù)廠商達(dá)成的協(xié)議,也就是由Sun定義一組接口,由數(shù)據(jù)庫(kù)廠商來(lái)實(shí)現(xiàn),并規(guī)定了JAVA開(kāi)發(fā)人員訪問(wèn)數(shù)據(jù)庫(kù)所使用的方法的調(diào)用規(guī)范。

                2JDBC的實(shí)現(xiàn)是由數(shù)據(jù)庫(kù)廠商提供,以驅(qū)動(dòng)程序形式提供。

                3JDBC在使用前要先加載驅(qū)動(dòng)。

                   JDBC對(duì)于使用者要有一致性,對(duì)不同的數(shù)據(jù)庫(kù)其使用方法都是相同的。

                   driver開(kāi)發(fā)必須要實(shí)現(xiàn)Driver接口。

                四種數(shù)據(jù)庫(kù)驅(qū)動(dòng)的實(shí)現(xiàn)方式

                JDBC-ODBC橋接式

                JDBC網(wǎng)絡(luò)驅(qū)動(dòng),這種方式是通過(guò)中間服務(wù)器的協(xié)議轉(zhuǎn)換來(lái)實(shí)現(xiàn)的

                JDBC+本地驅(qū)動(dòng),這種方式的安全性比較差

                JDBC驅(qū)動(dòng),由數(shù)據(jù)庫(kù)廠商實(shí)現(xiàn)。

           

          二.JDBCAPI

                java.sql包和javax.sql

                1.Driver接口 代表驅(qū)動(dòng)程序

          2.DriverManager類(驅(qū)動(dòng)管理器),它可以創(chuàng)建連接,它本身就是一個(gè)創(chuàng)建Connection的工廠(Factory)

                3.Connection接口,代表數(shù)據(jù)庫(kù)連接,會(huì)根據(jù)不同的驅(qū)動(dòng)產(chǎn)生不同的連接

                4.Statement接口,執(zhí)行sql語(yǔ)句

                5. PreparedStatement接口執(zhí)行sql語(yǔ)句(預(yù)編譯)

                6.CallableStatement接口 發(fā)送sql語(yǔ)句

                7.ResultSet接口(結(jié)果集),是用來(lái)接收select語(yǔ)句返回的查尋結(jié)果的。其實(shí)質(zhì)類似

          于集合。

                8.DatabaseMetaData  數(shù)據(jù)庫(kù)元數(shù)據(jù)

                9.ResultSetMetaData   結(jié)果集元數(shù)據(jù)

          10.Types:特殊的類。只包含靜態(tài)的常量,代表JDBC類型。JDBC類型是標(biāo)準(zhǔn)SQL類型的子集

          三、事務(wù)

                1).原子性,一致性,隔離性,持久性

          事務(wù)是一個(gè)數(shù)據(jù)操作單元,能夠保證在該單元內(nèi)執(zhí)行的多個(gè)SQL語(yǔ)句,或者一起成

          ,或者一起失敗.

                2).事務(wù)的并發(fā)控制:

                    (dirty)臟讀:一個(gè)事務(wù)能讀到另外一個(gè)事務(wù)沒(méi)有提交的數(shù)據(jù)

                    不可重復(fù)讀:在同一個(gè)事務(wù)的兩次查詢中,發(fā)現(xiàn)值不同,叫做不可重復(fù)讀.這是因?yàn)樵?/span>

          兩次查詢之間,另外一個(gè)事務(wù)修改了數(shù)據(jù)并提交了.

                    (phantom)幻影讀:在同一個(gè)事務(wù)的兩次查詢中,發(fā)現(xiàn)記錄的數(shù)目不同,叫做幻影讀.

          這是因?yàn)樵趦纱尾樵冎g,另外一個(gè)事務(wù)增加或者刪除了數(shù)據(jù)并提交了.

                3).隔離級(jí)別

                   Connection 類中的五個(gè)靜態(tài)常量

                   A.不使用事務(wù) TRANSACTION_NONE

                 B.允許臟讀    TRANSACTION_READ_UNCOMMITTED

                   C.不允許臟讀  TRANSACTION_READ_COMMITTED

                   D.防止不可重復(fù)讀,臟讀 TRANSACTION_REPEATABLE_READ

                   F.事務(wù)串行化  TRANSACTION_SERIALIZABLE

          四、JDBC編程步驟

                1,注冊(cè)加載一個(gè)driver驅(qū)動(dòng)

                2,創(chuàng)建數(shù)據(jù)庫(kù)連接(Connection

                3,創(chuàng)建一個(gè)Statement(發(fā)送sql

                4,執(zhí)行sql語(yǔ)句

                5,處理sql結(jié)果ResultSetselect語(yǔ)句)

                6,關(guān)閉sql結(jié)果ResultSet (如果有)

                7,關(guān)閉Statement

                8,關(guān)閉連接Connection

                注意:678兩個(gè)步驟必須要做的,因?yàn)檫@些資源是不會(huì)自動(dòng)釋放的,必須要自己關(guān)閉

           

                1,注冊(cè)加載驅(qū)動(dòng)driver,也就是強(qiáng)制類加載

                     一般來(lái)說(shuō)我們使用方法1

                     方法1 Class.forName(Driver包名.Driver類名)

                           eg:加載oracle

                           Class.forName("oracle.jdbc.driver.OracleDriver");

                     方法2Driver d=new oracle.jdbc.driver.OracleDriver();

                           DriverManager.registerDriver(d);

                     方法3java -Djdbc.drivers=驅(qū)動(dòng)全名 類名

           

                     OracleDriver的全名:oracle.jdbc.driver.OracleDriver

                     mysqlDriver的全名:com.mysql.jdbc.Driver org.gjt.mm.mysql.Driver

                     SQLServerDriver的全名:com.microsoft.jdbc.sqlserver.SQLServerDriver

                2,創(chuàng)建連接

                     DriverManager.getConnection(String url,String username,String

          password);

                     Connection連接是通過(guò)DriverManager的靜態(tài)方法getConnection(.....)來(lái)得到

          的,這個(gè)方法的實(shí)質(zhì)是把參數(shù)傳到實(shí)際的Driver中的connect()方法中來(lái)獲得數(shù)

          據(jù)庫(kù)連接的。

                OracleURL值是由連接數(shù)據(jù)庫(kù)的協(xié)議和數(shù)據(jù)庫(kù)的IP地址及端口號(hào)還有要連接的

          庫(kù)名(DatebaseName

                     Oracle URL的格式

                     jdbc:oracle:thin:@數(shù)據(jù)庫(kù)IP地址:端口號(hào):數(shù)據(jù)庫(kù)名(sid)

                     如:oracle所在服務(wù)器地址為192.168.0.254,而端口號(hào)為默認(rèn)的1521,數(shù)據(jù)

          庫(kù)名為tarena,那么URL就應(yīng)寫成

                     jdbc:oracle:thin:@192.168.0.254:1521:tarena       

                     MySql URL的格式

                     jdbc:mysql://數(shù)據(jù)庫(kù)IP地址:端口號(hào)/數(shù)據(jù)庫(kù)名

                     例: jdbc:mysql://localhost:3306/test

                     訪問(wèn)本機(jī)時(shí)IP地址用localhost127.0.0.1都可以         

                     SQLServer URL的寫法

                     例:jdbc:microsoft:sqlserver://localhost:1433

                3、創(chuàng)建Statement

                     使用Connection對(duì)象獲得一個(gè)Statement

                     Statement中的方法:

          1) executeQuery(String sql) 方法可以使用select語(yǔ)句查詢,并且返回一個(gè)結(jié)

          果集ResultSet,通過(guò)遍歷這個(gè)ResultSet,可以獲得select語(yǔ)句的查尋結(jié)果。

                     ResultSet rs = stmt.executeQuery(“select * from person”);

                     2executeUpdate(String sql) 方法用于執(zhí)行DDLDML語(yǔ)句,可以update

          delete操作。

                     此方法返回一個(gè)int類型的值,表示此條sql語(yǔ)句影響的記錄條數(shù)

                     Int count = stmt.executeUpdate(“delete from person where pid=1”);

                     Int count = stmt.executeUpdate(“update person set name=’jack’,age=’20’

          where pid=1”);

                     3execute(String sql) 這個(gè)方法的返回值是boolean類型

                     如果返回true就表示sql是一個(gè)select語(yǔ)句,然后通過(guò)getResultSet()獲得結(jié)果

                     如果返回false sql就是DML語(yǔ)句或者是DDL語(yǔ)句,即沒(méi)有結(jié)果集,

                     然后通過(guò)getUpdateCount()方法 獲得更新的記錄條數(shù)。

                     在不能明確傳入sql是何種類型的操作時(shí)使用此方法。

                     if (stmt.execute(sql)) {

                           ResultSet rs = stmt.getResultSet();

                     } else {

                           int count = stmt.getUpdateCount();

                     }

                     4getUpdateCount() 返回更新的記錄條數(shù)

                4.處理結(jié)果集ResultSet(結(jié)果集里存儲(chǔ)的是二維的結(jié)構(gòu),相當(dāng)于一張表)

                     ResultSet rs = stmt.executeQuery(“select pid, name, age from person”);

                     Person person = null;

                     while(rs.next) {

                           person = new Person();

                           person.setPid(rs.getInt(1));//jdbc下標(biāo)是從1開(kāi)始

                           person.setName(rs.getString(“name”));//也可使用列名來(lái)得到數(shù)據(jù)

                           person.setAge(rs.getInt(3));

                     }

                     1) next()方法會(huì)操作一個(gè)游標(biāo)從第一條記錄的前邊開(kāi)始讀取,直到最后一條記錄。

                           由于結(jié)果集返回來(lái)之后游標(biāo)的位置在第一條記錄的前面,所以調(diào)用next()

          法不會(huì)丟失數(shù)據(jù)。

                     2) getXXX(int index)其中XXX代表數(shù)據(jù)庫(kù)中存儲(chǔ)的數(shù)據(jù)類型相對(duì)應(yīng)的java數(shù)據(jù)

          類型,

                           此方法可以根據(jù)指定順序獲得字段值,注:順序是從1開(kāi)始的。

                      eg: int cid = rs.getInt(1);

                           String cname = rs.getString(2);

                     3) getXXX(String columnName):此方法可以根據(jù)指定字段的名字獲取字段的值

                           eg: int cid = rs.getInt("cid");

                           String cname = rs.getString("cname");

                     4updateXXX() XXX代表的是相應(yīng)的類型,無(wú)返回值

                     5)  isXXXX() XXXX代表的是游標(biāo)的位置FirstLast。。。返回布爾值

                5.資源的關(guān)閉順序:

                     要按先ResultSet結(jié)果集,然后Statement,最后Connection的順序關(guān)閉資源。

                     因?yàn)?/span>StatementResultSet是需要連接是才可以使用的,所以在使用結(jié)束之后

          有可能起他的Statement還需要連接,

                     所以不能現(xiàn)關(guān)閉Connection

                     //關(guān)閉結(jié)果集

                     if (rs != null) try {rs.close()} catch (SQLException e) { e.printStackTrace();}

                     //關(guān)閉Statement

                     if (stmt != null) try { stmt.close()} catch (SQLException e) {

          e.printStackTrace();}

                     //關(guān)閉鏈接

                     if (conn != null) try { conn.close()} catch (SQLException e) {

          e.printStackTrace();}

                6.PreparedStatement(預(yù)編譯的Statement)

                     PreparedStatement 用來(lái)執(zhí)行同構(gòu)的SQL,它的創(chuàng)建方式:

                     PreparedStatement pstmt = con.prepareStatement("insert into clazz values(?,?)");

                     可以使用參數(shù)替代sql語(yǔ)句中的某些參數(shù)使用"?"代替,他先將帶參數(shù)的sql語(yǔ)句發(fā)送到數(shù)據(jù)庫(kù),

                     進(jìn)行編譯,然后PreparedStatement會(huì)將參數(shù)發(fā)送給數(shù)據(jù)庫(kù)。

                     在使用PreparedStatement時(shí),設(shè)置相應(yīng)參數(shù)要指明參數(shù)的位置和類型,以及給出參數(shù)值

                     根據(jù)不同的參數(shù)類型使用不同的setXXX(參數(shù)的位置,參數(shù)值)來(lái)設(shè)置參數(shù)

                     結(jié)構(gòu)跟此方法類似:setInt(int parameterIndex, int x)

                     pstmt.setInt(1,i);

                     pstmt.setString(2,"xxx"+i)

                7.CallableStatement

                     CallableStatement是可以用非sql語(yǔ)句來(lái)訪問(wèn)數(shù)據(jù)庫(kù),他是通過(guò)調(diào)用存儲(chǔ)過(guò)程(PL/SQL)來(lái)訪問(wèn)數(shù)據(jù)

          庫(kù)的。

                     可以直接使用連接來(lái)調(diào)用 prepareCall(...)方法,來(lái)執(zhí)行這個(gè)存儲(chǔ)過(guò)程,"..."是存儲(chǔ)過(guò)程的名字。

                8.SQLException是檢查異常必須處理,要么throws ,要么try{}catch(){}

                   getErrorCode()可以獲得錯(cuò)誤碼,可以對(duì)錯(cuò)誤進(jìn)行查詢。

          五、元數(shù)據(jù)

                元數(shù)據(jù)就是描述數(shù)據(jù)庫(kù)或其組成部分的數(shù)據(jù)。(區(qū)別于存儲(chǔ)在數(shù)據(jù)庫(kù)中的實(shí)際數(shù)據(jù))

                它用來(lái)輔助我們更好的處理數(shù)據(jù)庫(kù)的用戶數(shù)據(jù)[通俗的講就是指容器的結(jié)果的信息]

          JDBC中有兩種元數(shù)據(jù),一種是數(shù)據(jù)庫(kù)元數(shù)據(jù)(DatabaseMetaData,另一種是結(jié)果集元數(shù)據(jù)(ResultSetMetaData

                1.數(shù)據(jù)庫(kù)元數(shù)據(jù)

                     如果要想了解數(shù)據(jù)庫(kù)的更多信息。可以從數(shù)據(jù)庫(kù)連接中獲取一個(gè)DatabaseMetaData

                     DatabaseMetaData  dmd=conn.getMetaData();

                     然后可以調(diào)用如下的方法獲得數(shù)據(jù)庫(kù)相關(guān)的信息

                     getURL(),獲得連接數(shù)據(jù)庫(kù)的URL

                     getDatabaseProductName() 獲得數(shù)據(jù)庫(kù)產(chǎn)品的名稱

                     getDriverVersion() 獲得JDBC驅(qū)動(dòng)程序的String形式的版本號(hào)

                     getTables()獲得數(shù)據(jù)庫(kù)中該用戶的所有表

                     getUserName() 獲得數(shù)據(jù)庫(kù)用戶名。

                2.結(jié)果集元數(shù)據(jù)

                     ResultSet rs=ps.executeQuery();

                     ResultSetMetaData m=rs.getMetaData();

                     getColumnCount(),獲得實(shí)際列數(shù)

                     getColumnName(int colnum),獲得指定列的列名

                     getColumnType(int colnum),獲得指定列的數(shù)據(jù)類型

                     getColumnTypeName(int colnum),獲得指定列的數(shù)據(jù)類型名

                例如:ResultSetMetaData md = rs.getMetaData();

                                // 得到字段個(gè)數(shù)

                                int cols = md.getColumnCount();

                                // 根據(jù)字段個(gè)數(shù)遍歷和打印結(jié)果集

                                StringBuffer sb = new StringBuffer();

                                for (int i = 0; i < cols; i++) {

                                      sb.append(md.getColumnName(i + 1) + " ");

                                }

                     動(dòng)態(tài)獲得表結(jié)構(gòu)

           

          六、JDBC2.0新特性

                默認(rèn)方式獲得的結(jié)果集都是1.0的結(jié)果集

                能否使用JDBC2.0 ResultSet的新特性要看數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序是否支持。

                1.可滾動(dòng)結(jié)果集(可雙向滾動(dòng)),(了解 能說(shuō)出結(jié)果集滾動(dòng)的方法即可)

                     這種結(jié)果集不但可以雙向滾動(dòng),相對(duì)定位,絕對(duì)定位,并且可以修改數(shù)據(jù)信息。

                     要使用可滾動(dòng)結(jié)果集時(shí),要在Statement創(chuàng)建時(shí)指定參數(shù),才可以使用

                     Statement st=null;int,int(可滾動(dòng)特性,可更新特性)

                     st=con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_UPDATABLE) 

                     PreparedStatement

          ps=con.createPrepareStatement(sql,ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_

          UPDATABLE);

                     ResultSet rs=ps.executeQuery(sql);

                滾動(dòng)特性

                     next(),此方法是使游標(biāo)向下一條記錄移動(dòng)。

                      previous() ,此方法可以使游標(biāo)向上一條記錄移動(dòng),前提前面還有記錄。

                     absolute(int row),絕對(duì)定位函數(shù)可以使用此方法跳到指定的記錄位置。定位成功返回true,不成功返

          false,返回值為false,則游標(biāo)不會(huì)移動(dòng)。

                     afterLast() ,游標(biāo)跳到最后一條記錄 之后,(結(jié)果集一回來(lái)時(shí)就有的位置)。無(wú)返回值。

                     beforeFirst() ,游標(biāo)跳到第一條記錄 之前,(結(jié)果集一回來(lái)時(shí)就有的位置)。(跳到游標(biāo)初始位)無(wú)返回

                     first(),游標(biāo)指向第一條記錄。

                     last(),有彪指向最后一條記錄。

                     relative(int rows),相對(duì)定位方法,參數(shù)值可正可負(fù),參數(shù)為正,

                     游標(biāo)從當(dāng)前位置向下移動(dòng)指定值,參數(shù)為負(fù),游標(biāo)從當(dāng)前位置向上移動(dòng)指定值。

                ResultSet可滾動(dòng)性的屬性值:

                     TYPE_FORWARD_ONLY ,單向,該常量指示指針只能向前移動(dòng)的 ResultSet 對(duì)象的類型。不可滾動(dòng)。

                     TYPE_SCROLL_INSENSITIVE ,雙向,對(duì)數(shù)據(jù)庫(kù)的變化不敏感

                     TYPE_SCROLL_SENSITIVE ,雙向,對(duì)數(shù)據(jù)庫(kù)的變化敏感

                     ResultSet 對(duì)象的類型。該特性某些數(shù)據(jù)庫(kù)不支持。

                ResultSet可更新性的屬性值: 

                     CUNCUR_READ_ONLY,不可更新的結(jié)果集

                     CUNCUR_UPDATEABLE,可更新的結(jié)果集

                2.可更新的結(jié)果集:(不常用,也不推薦使用)(了解)

                     如果你想能夠編輯結(jié)果集中的數(shù)據(jù),并且將結(jié)果集上的數(shù)據(jù)自動(dòng)反應(yīng)到數(shù)據(jù)庫(kù)中,

                     那么就必須使用可更新的結(jié)果集,可更新結(jié)果集不一定是可滾動(dòng)的,獲得可更新結(jié)果集的方法:

                Statement  

          stat=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATE

          ABLE);

                     這樣,調(diào)用executeQuery()方法返回的結(jié)果集就是可更新的結(jié)果集。

                例如:

                     String  query="SELECT *  FROM  books";

                     ResultSet  rs=stat.executeQuery(query);

                     While(rs.next){

                           If(.......){

                                    Double inscrease=.......;

                                    Double  price=rs.getDouble("Price");

                                     rs.updateDouble("Price",price+inscrease);

                                     rs.updateRow();

                         }

                     }

          所有的對(duì)應(yīng)于SQL類型的數(shù)據(jù)類型都配有updateXXX方法。與getXXX方法類似。使用updateXXX方法是必須指定列的名稱或序列號(hào)。

                然后,可以給 該字段設(shè)置新的值。

                updateXXX方法改變的只是結(jié)果集中的行值,而非數(shù)據(jù)庫(kù)中的值。當(dāng)更新完行中的字段值后,必須調(diào)用

          updateRow方法,這個(gè)方法將當(dāng)前的行中所有更新信息發(fā)送給數(shù)據(jù)庫(kù)。如果沒(méi)有調(diào)用updateRow方法就將

          游標(biāo)移動(dòng)到其他行上。那么所以的更新信息就將被丟棄,而且永遠(yuǎn)不會(huì)被傳遞給數(shù)據(jù)庫(kù)。還可以調(diào)用cancelRowUpates方法來(lái)取消對(duì)當(dāng)前行的更新。

                以上是更新數(shù)據(jù)庫(kù)中的一行記錄,如果想在數(shù)據(jù)庫(kù)中添加一條新的記錄,首先需要使用moveToInsertRow

          ()方法將游標(biāo)移動(dòng)到特定的位置。然后調(diào)用updateXXX()方法在插入行的位置上創(chuàng)建一個(gè)新的行。然后調(diào)用

          insertRow()方法將新建的行發(fā)送給數(shù)據(jù)庫(kù)。完成插入操作后在調(diào)用moveToCurrentRow()方法講游標(biāo)移回到調(diào)用moveToInsertRow方法之前的位置:

                例子:

                     rs.moveToInsertRow();

                     rs.updateString("Title",title);

                     rs.updateString("Price",price);

                     ..........

                     rs.insertRow();

                     rs.moveToCurrentRow();

                如果要?jiǎng)h除一行調(diào)用rs.deleteRow()即可刪除結(jié)果集和數(shù)據(jù)庫(kù)中的一行

                能否使用可更新結(jié)果集,要看使用的數(shù)據(jù)庫(kù)驅(qū)動(dòng)是否支持,還有只能用于單表且表中有主鍵字段(可能會(huì)是

          聯(lián)合主鍵),不能夠有表連接,會(huì)取所有非空字段且沒(méi)有默認(rèn)值。結(jié)果集用select * from t也不行,不能用

          *,不能排序

                3,批處理更新 (熟記于心)

                     Statement.

                     addBatch(String sql) 方法會(huì)在批處理緩存中加入一條sql語(yǔ)句

                     executeBatch() ,執(zhí)行批處理緩存中的所有sql語(yǔ)句。

                     PreparedStatement.   先準(zhǔn)備一組參數(shù)

                     addBatch() 將一組參數(shù)添加到此 PreparedStatement 對(duì)象的批處理命令中。

                     executeBatch() 將一批命令提交給數(shù)據(jù)庫(kù)來(lái)執(zhí)行,如果全部命令執(zhí)行成功,則返回更新計(jì)數(shù)組成的數(shù)組。

                     PreparedStatement中使用批量更新時(shí),要先設(shè)置好參數(shù)后使用addBatch()方法加入緩存。

                     注意:批量更新中用更新或插入語(yǔ)句

          面向?qū)ο蟮臄?shù)據(jù)庫(kù)設(shè)計(jì)

           

          Id通常是用來(lái)表示記錄的唯一性的,通常會(huì)使用業(yè)務(wù)無(wú)關(guān)的數(shù)字類型

          Object id 對(duì)象的idsequence只有Oracle才可用,對(duì)象idOID)使用高低位算法先生成高位,在生成低位,通過(guò)運(yùn)算獲得對(duì)象id

          類應(yīng)當(dāng)對(duì)象到表,屬性對(duì)應(yīng)字段,對(duì)象對(duì)應(yīng)記錄。

           

          類繼承關(guān)系對(duì)應(yīng)表,

          1,每個(gè)類建一個(gè)表,為父子類每個(gè)類都對(duì)應(yīng)的創(chuàng)建表,這種方法類關(guān)系清晰,但是如果類比較多就不適合了

          2,只有具體類才建表,也就是把父類中的屬性均勻分配到子類的表中,也就是父類不建表,這種表關(guān)系不能使用多態(tài)

          3,所有類對(duì)應(yīng)一張表,這種方法是在表中加上一個(gè)字段來(lái)區(qū)分父子類,但是只能用于類屬性較少的情況下,而且數(shù)據(jù)會(huì)有冗余。

           

          類關(guān)聯(lián)關(guān)系對(duì)應(yīng)表

          1,一對(duì)一關(guān)聯(lián),類關(guān)系對(duì)應(yīng)成表時(shí)有兩種做法,一是引用主鍵,也就是一方引用另一方的主鍵既作為外鍵又作為自身的主鍵。

                二是外鍵引用,一方引用另一方的主鍵作為自身的外鍵,并且自己擁有主鍵。

          2,一對(duì)多關(guān)聯(lián),也就是多端引用一端的主鍵當(dāng)作外鍵,多端自身?yè)碛兄麈I。

          3,多對(duì)多關(guān)系,多對(duì)多關(guān)系是通過(guò)中間表來(lái)實(shí)現(xiàn)的,中間表引用兩表的主鍵當(dāng)作聯(lián)合主鍵,就可以實(shí)現(xiàn)多對(duì)多關(guān)聯(lián)。

           

           

          posted on 2009-03-31 19:41 faye 閱讀(711) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 文山县| 东平县| 龙江县| 于都县| 宕昌县| 聂拉木县| 淅川县| 天等县| 明溪县| 庐江县| 新余市| 唐河县| 繁峙县| 阜南县| 水城县| 绥芬河市| 周至县| 青浦区| 平乐县| 武功县| 河间市| 绥芬河市| 彝良县| 松桃| 霍林郭勒市| 阿图什市| 进贤县| 开阳县| 长垣县| 梓潼县| 弥渡县| 景洪市| 平塘县| 织金县| 内乡县| 邵武市| 肃北| 延安市| 桂东县| 侯马市| 囊谦县|