• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            數據庫設計之“有時不得不違背的第三范式”

            在博客園上看到了一篇關于數據庫范式的文章《數據庫設計中的五個范式》:
             
            第三范式規則查找以消除沒有直接依賴于第一范式和第二范式形成的表的主鍵的屬性。我們為沒有與表的主鍵關聯的所有信息建立了一張新表。每張新表保存了來自源表的信息和它們所依賴的主鍵。  
             
            關于第三范式的思想,我想有很多朋友都熟悉,在數據庫設計時,也是我們盡可能采用的范式之一,第三范式的出發點是什么?就是盡可能的減小數據冗余、并也能得到數據的整潔性,提高維護性,不容懷疑,第三范式是我們努力、必須要去遵從的。
             
            然而,有很多朋友把第三范式作為不死的法寶,但其實在實際的應用中,我們還是要從不同的業務出發,要合理的應用第三范式。下面我也就簡單的舉個例子:
               
            一張訂單會關聯很多的基礎資料,如:客戶,付款條款,貨運方式等,這些信息是有專門表進行維護的,在下訂單時也是用下拉框選擇的,在保存訂單信息時,按照第三范式的要求,那應該只保存對應的主鍵值就OK了。因為這樣可以避免數據冗余,但對我來說,我不會這樣做,我會把客戶的名稱、聯系電話、付款條款名稱等訂單上要求記錄的信息直接COPY到訂單的表中。
              
            這樣看來,我們違背了第三范式,是的,但在這里,我們違背第三范式也是有理由的:
               1
            我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
               2
            我也不想,因為下了這張訂單了,而嚴格控制付款條款的刪除功能,這也不合理,憑啥不能刪除了?下個月這個條款確實永遠不會采用了。
               3
            我也不想,付款條款修改后,導致以前所有采用此付款條款的訂單都變成新的條款,那在系統中的訂單如何與手頭的紙張訂單再對應,這肯定也不合理。

             
            所以,我的設計原則是,對于這種訂單我們應該采用隔離的方式來對待,讓基礎數據COPY到訂單中,這當然會違背所謂的第三范式,但這也是實際的需要啊。理論與實際是有差別的。
             
            訂單--這種在現實中以實物的方式存在,實物具有與基礎數據的參考性,而不是關聯性,基礎數據只能是作為訂單這個實物的一個參考,而不是關聯,這可以稱為獨立性”;再者,訂單具有一定的歷史性,因為是實物,在實際的過程中,是即時生成的,那么在生成的當時去參考了基礎數據,訂單就在當時被確定,確對不能因為基礎數據的修改而導致訂單被無辜變性了,這也就是訂單的歷史性,當以后翻閱這些紙張訂單時也能對應上系統里的訂單。

              
            這是我所理解的最典型的例子,在實際的系統設計中,我們應該多思考一下,是不是要采用第三范式,不要再盲目追捧了。


             
            以上純屬我個人意見,僅供參考,歡迎大家討論。

            Feedback

            #1    回復  引用  查看    

            2005-05-08 14:23 by Lostinet     

            例如今天賣了2個面包,價格是3塊,那么Sales表里應該把當時的價格也紀錄了。而不只是紀錄了這個面包的型號,因為面包的價格是會變化的。
            關鍵是要對數據的含義與關系有清晰的認識。而這種紀錄本身不屬于冗余,并不和數據庫設計的理論有沖突的地方。

            就客戶改名字的說法,訂單紀錄的數據可以當作是訂單時的客戶名稱,與客戶表的當前名稱有著不同的意義,這就不是冗余。


            #2    回復  引用  查看    

            2005-05-08 14:25 by 嘿嘿     

            范式原則是用于指導性地設計數據的存儲結構的,僅僅只是理論。必要的時候是需要反范式,或者容忍一定的數據冗余,使得系統的性能或邏輯清晰性上更好。

            范式是一種基于純粹的從數據存儲量上來優化數據結構的方式,并不是一個非常通用的東西。

            另外:
            “1
            我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
             2 我也不想,因為下了這張訂單了,而嚴格控制付款條款的刪除功能,這也不合理,憑啥不能刪除了?下個月這個條款確實永遠不會采用了。

            上述情況,實際上可以考慮采用倉庫性質的數據管理方法:即,對于所有的數據,分為可用與不可用,放在不同的表間,然后可以把其中的數據挪來挪去。

            你說的情況非常現實,從業務角度出發,將數據結構優化為最高存儲效率的是沒有意義的,范式更多是一種指導,而不是原則。

            #3    回復  引用  查看    

            2005-05-08 14:39 by 寒楓天傷     

            我覺得這是理論與實踐中的區別,或者說,一般人對范式的理解并不對。

            一般而言,范式是作為指導性原則存在的,范式提供了一種指導性的依據,可以實現最終冗余數據的消除。但在實際上,冗余數據并不是違法的,也不是不允許的,除了性能上的需要外,很多情況下都需要冗余數據來實現參照完整性。

            數據庫設計最主要的概念之一就是參照完整性,一個完整的數據庫中,存儲的關聯信息,應該是要么都存在,要么都消失,如樓主說的:
            我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
            理論上,如果依照范式實施的參照完整性,要求這里的付款條款所關聯的訂單全部都刪除,否則的話,該付款條款是不應該刪除的。

            不過,更重要的是:樓主所說的付款條款訂單間應該是弱耦合關系,它們應該是分開的。這個矛盾產生兩張有關聯的表的存儲方式上。這個情況而言,付款條款應該是作為輔助表而存在的,有可能這個表僅僅是為了提供下拉列表或其它什么方式的便利性輸入接口,那么付款條款本質上只是存儲了的數據,它與訂單間不應該有關系。

            樓主的做法從這個角度上而言,并未違反第三范式。第三范式應該集中應用于有業務關系的表,而不應將輔助表也包括在內。

            #4    回復  引用  查看    

            2005-05-08 14:56 by hudan     

            基本同意樓主的觀點,但就樓主提出的例子談一下我的想法:
            就你說的這種,我的做法是在"付款條款"基本表中增加一列是否刪除的標識列,刪除的時候修改"刪除標識",以后用戶下訂單的時候就不會看到這個條款了,但是查詢歷史數據的時候仍然可以查詢到以前的條款.
            對于你說的第三點"系統中的訂單如何與手頭的紙張訂單再對應",我的這種做法就無法實現對應了.就會全部顯示修改后的條款.

            有些情況下為了提高查詢速度也冗余幾個字段,我認為是值得的.






            #5    回復  引用  查看    

            2005-05-08 15:07 by mikespook     

            《迦勒比海盜》里面有一句話:法典,更像是指南,而不是準則……”

            #6 [樓主]   回復  引用  查看    

            2005-05-08 15:21 by 聽棠.NET     

            @寒楓天傷 :
            我覺得這也是指關聯,因為我們也可以采用第三范式來實現,只是訂單在這種情況下會遇到好多的問題.

            在訂單的設計中,我一般會有條款ID”條款名稱,也就是我會把主鍵對應上以后,把Name也帶過來,之所以要帶入"條款ID",主要還是因為訂單需要修改,在修改時,可以默認選中原來的值。而條款名稱的帶入就是我前面的說的原因。
            因此,從這一點來說,這些確實是違背了第三范式

            #7    回復  引用  查看    

            2005-05-08 18:17 by lay     

            呵呵,我覺得樓主舉的例并不是違反了,字典表相對來說要特殊些。最終還是得根據具體業務來定

            #8    回復  引用  查看    

            2005-05-08 18:58 by 上山砍柴去     

            “1我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
            ==為何要允許刪除付款條件?不可以設為失效嗎?

            2
            我也不想,因為下了這張訂單了,而嚴格控制付款條款的刪除功能,這也不合理,憑啥不能刪除了?下個月這個條款確實永遠不會采用了。
            ==不能刪除就是不能刪除,規定下來不可以嗎?同樣,設為失效不行嗎?

            3
            我也不想,付款條款修改后,導致以前所有采用此付款條款的訂單都變成新的條款,那在系統中的訂單如何與手頭的紙張訂單再對應,這肯定也不合理。
            ==付款條件可以隨意修改的嗎?同樣,需要修改的不可以新建一個條件嗎?

            我認為,你的數據庫這樣設計是非常不成功的。就因為你上面的理由就造成成千上萬條記錄的冗余?這合理嗎?

            一已之見,只承擔有限責任。。。

            #9    回復  引用  查看    

            2005-05-08 19:26 by      

            其實樓主說的很有理,好多時候,我們要因事而宜不能把住死理不放,但是一個理論的存在是有一定的道理的,起碼在一段時間內,所以我想去應用第三式,還是必要的

            #10    回復  引用  查看    

            2005-05-08 20:12 by 紅移     

            可以這樣設計

            訂單表:
            訂單號(主鍵)
            條款號(外鍵)
            [
            其它內容]

            條款表:
            條款號(主鍵)
            有效標記(bit
            條款內容
            [
            其它內容]

            列訂單時只列出條款表中有效標記為1的條款。刪除條款的前提是該條款不再有人用到(在訂單表中)。如果有人用到,則只是把有效標記設為0。當刪除訂單時,檢查條款表中相應的條款,如果它已經無效并且除了本訂單外無其它人用到,則順便刪除該條款。

            #11    回復  引用  查看    

            2005-05-08 20:29 by 一川煙草     

            我搞8年的業務系統,從單機程序到800多個表的大系統。
            我的感覺是冗余確實是非常必要的。
            用空間換取效率。
            我有一個check表,餐飲系統的。
            包括了開單員
            開單銷售點
            開單餐段

            結單員
            結單銷售點
            結單餐段


            #12    回復  引用  查看    

            2005-05-08 20:36 by 一川煙草     

            我的感覺是冗余確實是非常必要的。
            用空間換取效率。
            我有一個check表,餐飲系統的。
            包括了開單員
            開單銷售點
            開單餐段
            開單終端
            結單員
            結單銷售點
            結單餐段
            結單終端
            這些都是外鍵,而且每個外鍵的描述都包括,中文,英文,其它語言三個描述。
            在給客戶顯示數據的時候,得根據當前語言顯示對應描述。這樣的查N個表返回數據,一個稍有規模的餐廳,每天的單數有上千張。這樣的查詢效率極地下。
            經過冗余之后,以上8個字段我們把它冗余為32個。把全部描述都丟到check表,查詢效率成倍提升。并且簡化了程序員的開發。
            對于設置表的刪除,我的看法是為什么要真的刪除呢?設置表的主鍵完全可以設計成用戶不可見的。用戶仍然可以刪除,不過真實的數據只不過作了個刪除標記而已。


            #13 [樓主]   回復  引用  查看    

            2005-05-08 21:27 by 聽棠.NET     

            @上山砍柴去 :
            其實我非常不想跟你討論這些問題,你說的幾個跟我的意思根本不是一回事。你可以用是否有效來實現,你的意思是所有的基礎都有是否有效,可客戶就是不喜歡這種是否有效的標志,"是否有效"是在客戶"暫時不用"的情況下會采用,知道什么叫"暫時"嗎?再者,時間一長你搞那么多"無效"的多惡心啊。
            還有我說的就是能允許客戶刪除,你憑什么不讓客戶刪除,你以為這是給客戶考慮嗎?
            自己去悟吧。

            #14    回復  引用  查看    

            2005-05-08 21:52 by rIPPER     

            客戶一定要直接看到這個有效標志么,他不喜歡看,你可以不讓他看到,這很容易嘛。

            要玩客戶不要被客戶玩,他說要刪除你就真從數據庫里面刪掉一條記錄?

            #15    回復  引用  查看    

            2005-05-08 22:10 by 一川煙草     

            我道是同意作標記,對于用戶來說,什么叫刪除?界面上看不到了就是刪除。

            #16 [樓主]   回復  引用  查看    

            2005-05-08 22:25 by 聽棠.NET     

            我知道大家可以作標記,我也是對一些需要用到標記的我會用,但如果那些根本沒必要用的,都采用標記的方式來處理,我覺得很不爽,明明已經不再可用的東西,在數據庫里放著,太惡心了。。還招來程序的麻煩。。

            #17    回復  引用  查看    

            2005-05-08 22:40 by 小陸     

            我覺得冗余帶來的最大的問題在于難以同步,占用空間倒是其次。

            #18    回復  引用  查看    

            2005-05-08 23:01 by 楚瀟     

            經過實際的項目的話,就明白樓主所說的道理了。
            做一個刪除標志也是可行的,但是很多的時候,沒有樓主說的方法好。


            #19    回復  引用  查看    

            2005-05-09 00:12 by yfmine     

            To:hudan
            個人意見,在數據庫里只添加新規則,不能改變已有規則,任何改動都視作新添加,這樣就能實現第三點了。不過這樣的數據也。。。

            #20    回復  引用  查看    

            2005-05-09 00:57 by wljcan     

            同意 寒楓天傷 的觀點。


            從文中的描述來看,應該是弱耦合,但是這段話又有些問題:

            *****
            在訂單的設計中,我一般會有條款ID”條款名稱,也就是我會把主鍵對應上以后,把Name也帶過來,之所以要帶入"條款ID",主要還是因為訂單需要修改,在修改時,可以默認選中原來的值。而條款名稱的帶入就是我前面的說的原因。

            既然已經 將Name copy過來了,為什么還要ID呢?默認選中原來的值好像不成立。

            另外,技術討論沒有必要有這么濃的火藥味。 :=

            #21    回復  引用  查看    

            2005-05-09 08:56 by 老翅寒暑     

            關于文中的訂單中客戶信息部分一定是需要copy到訂單表中的。這么多人考慮問題,怎么沒有人從法律效力方面來考慮呢?做一個系統首要要保證的是呈現的統一性,一個訂單錄入之后,只要沒有修改,無論多長時間,它的輸出格式和內容都不能有變化。這個是法律意義上的完整性。總不能今天訂單上是xx公司,明天xx公司改名成了xxx有限公司,難道之前和xx公司的訂單(或者合同)就要自動變成xxx有限公司?

            #22 [樓主]   回復  引用  查看    

            2005-05-09 09:15 by 聽棠.NET     

            @老翅寒暑 :
            我說的就是你指的意思,一張訂單已經確定,那么具有獨立性與歷史性。

            @
            上山砍柴去 :
            客戶說是保留,那你當然保留好了,我沒有否認這一點啊,但就怕客戶說不要保留,你卻偏偏要保留啊。至于數據冗余你看下面的。

            至于為什么還要ID呢?就是有可能會進行修改,那么如果不帶ID過去,修改時如何選中默認值,要是不能默認選中,結果客戶修改只是為了修改其它的一個屬性,而這個ID可能會在不注意的情況下被修改掉了。因為是下拉框的。
            至于作標記,也是一種方式,比如客戶說給作個標記或者是此值是應該具有暫時不用的情況,那么用標識當然是最好的。
            就像老翅寒暑 說的,一張訂單是實物,在業務實際中明明確確存在,要是從法律上講也具有法律,就算沒有法律性,我們也要把它視為一個獨立性,有朋友說,以后修改怎么辦?一張訂單在當時下達,就具有當時的即時性與歷史性,不可能因為你以后的基礎數據的修改而導致訂單失去原來的屬性,因此這些所謂的冗余只是從"第三范式"上講的,而在實際的業務中,其實沒有所謂的冗余


            #23    回復  引用  查看    

            2005-05-09 09:39 by na     

            如果你要隔離,那還有很多要隔離哦....
            為何不在刪除條款時看看是不是已經用過這個條款呢?
            基礎數據如果使用過是不給刪除的。

            #24    回復  引用  查看    

            2005-05-09 09:41 by 上山砍柴去     

            同意樓上的。
            ==================
            我并沒有受傷,比你刻薄的人多的是。
            有人附和是因為他們比你更沒有經驗,至少站在管理的角度來講,你這樣的觀點更是不恰當的。
            作為基礎數據,修改和刪除的權限都是比較高的,特別是這種有關聯其它數據的基礎數據,使用后更是不能隨意修改和刪除的,這在系統一級就應該予以禁止。系統級不能解決的,就要在管理一級予以解決。
            如果依你這樣的設計,那么其它的基礎數據不都要帶進別的表中去?產品數據,供貨商數據,客戶數據,。。。。等等等等。你這樣的數據設計有你認為是成功的嗎?
            你認為沒法跟我說,至少你覺得說服我有難度,我認為你這樣的觀念去做需求分析肯定是失敗的。最終出來的產品也肯定是個N不像產品。懂系統設計沒什么也不起,隨便找幾個人來都會做。反正都是客戶說了算。出了錯也是客戶自已找的。

            #25    回復  引用  查看    

            2005-05-09 09:56 by 小陸     

            根據文中的描述, 訂單記錄以后, 需要保留當時即時性和歷史性, 所以, 保留這些數據不能叫做冗余, 因為這些信息是必要. 所以從原則上說不違反第三范式.

            關鍵在于保留的方式. 既然將name已經復制過來了, id我覺得就是冗余了, 并且這兩個數據可能是不一致的, 如果以后需要修改的話, 直接顯示name就是了. 如果要便于用戶輸入, 可以使用輸入+選擇的方式.
            另一種做法就是保留每一個配置的版本, 每當用戶修改或者刪除一個配置數據, 不是實際的進行修改, 而是添加新的version, 這樣的方式是最好的, 完全符合第三范式.

            至于客戶要求刪除, 我理解是: 客戶看不見的就可以認為刪除了, 沒必要真的從物理上刪除掉.

            沒有什么原則是"不得不違背", 干出違背原則的事情一定要有更加有力的原則作為后盾. 比如: 適當冗余可以提高運行效率, 合理冗余可以增加系統容錯性. 如果單純為了簡化開發的過程, 我的體會是: 沒有冗余開發最簡單.

            #26 [樓主]   回復  引用  查看    

            2005-05-09 10:20 by 聽棠.NET     

            @小陸 :
            ID
            可以考慮不保留,確實可以直接修改NAME,因為從某種意義上說,參考的數據COPY過來后,就認為已經確定了。

            至于刪除的控制,有些基礎數據是需要使用控制來限制的,但不是全部。為何有人不思考實際中的一些差別呢。
            na
            說有很多要隔離??也不是啊,具有獨立性與歷史性的實物,是建議要隔離的。

            上山砍柴去說這么多人都是沒有經驗的??
            我真不知道,是不是很有經驗的人跟你一樣,所有的基礎數據都采用刪除控制來做的,你可以去調查一下。

            #27    回復  引用  查看    

            2005-05-09 10:37 by ayya__@hotmail.com     

            對于主表的刪除當然是用標記來做最好.
            如果以后客戶又需要用已經刪除的數據怎么辦?

            #28 [樓主]   回復  引用  查看    

            2005-05-09 10:41 by 聽棠.NET     

            @ayya__@hotmail.com :
            對,如果那些需要暫時不用的,是應該要用標記來做的。應該可以修改狀態,也可以刪除吧,要是他們確實想刪除。
            其實這種刪除不刪除無所謂了,問題是基礎數據應該COPY過去。

            #29    回復  引用  查看    

            2005-05-09 10:59 by Laser.NET     

            我個人比較贊同Lostinet的看法,其實不能算是違反第三范式。

            你在訂單表中存儲的是 那個訂單當時的客戶信息那個訂單當時的付款條款這些信息離開了那個訂單就沒有意義,所以它們完全依賴于訂單主鍵,而那個訂單也需要這些信息,在你所講的業務環境下它們對訂單來講必不可少,所以這本來就符合第三范式:)


            #30    回復  引用  查看    

            2005-05-09 11:02 by Austin leng     

            有道理喲,想問一下聽棠.NET,一個表里的字段數如果太多,你說有沒有問題,比如有張表TestTable,里面包含了60多個字段,你認為這有不有問題?

            #31    回復  引用  查看    

            2005-05-09 11:05 by Austin leng     

            數據庫設計,唉,很重要,哪位牛人推薦一本牛書,謝謝啦

            #32 [樓主]   回復  引用  查看    

            2005-05-09 11:15 by 聽棠.NET     

            其實從業務角度講,這種數據的COPY不能算是違反第三范式,那看一張主表可能會有相當多的關聯,那么也是要根據這張主表的信息情況,比如訂單,那些訂單本身所固有的屬性應該從基礎表COPY過來,而對于訂單類型可能不屬于訂單本身客觀存在的屬性,那么我們可以采用外鍵關聯的方式。象這種那么在刪除上是需要作限制的。

            #33    回復  引用  查看    

            2005-05-09 14:50 by Arming     

            大家討論這么多,我看基本上是兩種觀點:1Copy2是外鍵引用,但通過刪除標志控制。
            第一種表面上看是不違反第三法則,因為它可慮到條款的變更。寒楓天傷和 聽棠.NET都說了相應理由。
            這里的關鍵也就在于條款,老翅寒暑也明確提出了條款的業務含義。那么條款信息也不是簡單的數據字典業務所能涵蓋。條款的信息維護和訂單引用條款的地方就必須有些特殊的代碼來體現這個特殊性。
            通過直接Copy來保證訂單的法律性和新訂單使用最新條款,確實能節省代碼量,但數據冗余也是毋庸置疑的,試想,一個2000字左右的協議,每個訂單都擁有一份,而我這條款實際上也就兩三年一變。
            如果對條款信息引入一個版本概念,或者是否啟用概念(上山砍柴的一個觀點,不過他的口氣確實不好,不是討論問題的態度),實際上確實也應該存在這么一個概念,(注意,不是所有的引用信息都是如此維護。比如性別)。條款一旦被某訂單引用,就不允許修改或刪除,只能以版本變更方式變更。
            對無效條款的刪除(太多了確實不爽),可以在條款維護業務里控制,比如顯示某條款當前有多少訂單引用了,不過這只是易用性問題。可以通過增強界面控制實現。
            至于新訂單時能使用什么條款,這也是具體業務決定,我覺得界面上如何顯示,下拉框,還是彈出窗口,都不應該在此問題內討論。通常會在一個條款集合類提供一個靜態方法,提取合適的條款集合作為新訂單的選擇。
            訂單修改時,是否能重新選擇條款,或者此時條款剛剛更新,是否自動啟用新條款,這些都由具體業務來決定,也不是此問題范疇。

            BW
            :我在設計或開發時也不喜歡被條條框框約束。一切根據具體情況而定,假如項目小,或時間緊,資源不足,再或者這個條款長度也不長,我會毫不猶豫地使用Copy
            但假如條款確實長到讓我感覺冗余比較大,以及后期的可維護性。確實應該花時間考慮如何設計條款信息維護的業務。


            #34    回復  引用  查看    

            2005-05-09 15:30 by step     

            我碰到的應用也用到了冗余,當時覺得不符合范式要求,總是不情愿的認同,今天終于心服了。總是被理論束縛的心態很不舒服啊!

            #35 [樓主]   回復  引用  查看    

            2005-05-09 15:38 by 聽棠.NET     

            @Arming :
            你的觀點跟我們大致一樣,只是你可能沒搞清楚什么叫付款條款,英文名叫“Payment Term”,它不是一個2000字的協議,只是說明30天付款還是60天付款。
            給你看個圖:

             clip_image001

            #36    回復  引用  查看    

            2005-05-09 16:46 by rIPPER     

            payment term term在這里翻譯作條款,還要搞清楚?

            term
            n.

            1.
            A. A limited period of time.
            B. A period of time that is assigned to a person to serve: a six-year term as senator. See Synonyms at period.
            C. A period when a school or court is in session.

            2.
            以下略 ...

            你們那兒做l10n的太爛了,趕快建議老板辭掉他 :)

            #37 [樓主]   回復  引用  查看    

            2005-05-09 17:08 by 聽棠.NET     

            clip_image002

            老兄,在SAP里全都翻譯成付款條款的!!

            你查了查字典就以為可以想翻什么就翻什么嗎?

            不了解ERP也不至于要把老板炒了吧???


            早知道我就把文章寫成Payment Term了,那估計你肯定知道是什么意思了。哦,你不信的話用Google搜一下吧。

            #38    回復  引用  查看    

            2005-05-09 18:35 by james wong     

            Shit, 各人應用的環境不一樣,各人的經驗也不一樣。干嘛爭來爭去的?哪個你用好了沒問題就是對的,否則就是錯的。別人是對的你拿過來不一定是對的,別人是錯的也不一定在你那里就也是錯的。既然別人是對的你也不一定是對的,別人是錯的你也不一定是錯的,那這個問題也就是不對不錯的。那么,那么還要討論誰對誰錯做什么呢??

            打雷了。。下雨了。。。大家快收衣服啊。。。

            #39    回復  引用  查看    

            2005-05-09 19:17 by Arming     

            SAP里全都翻譯成付款條款” ,這樣看起來應該是沒有什么討論必要了。

            #40    回復  引用  查看    

            2005-05-09 19:39 by rIPPER     

            原來是sapl10n做得爛 ;) 不知道包給哪個公司做的,嘿嘿

            #41    回復  引用  查看    

            2005-05-09 20:49 by 知道得越多知道的越少     

            "有道理喲,想問一下聽棠.NET,一個表里的字段數如果太多,你說有沒有問題,比如有張表TestTable,里面包含了60多個字段,你認為這有不有問題?"

             

             字段多不是問題,你可以去看看SPS的數據表Userdata,微軟為每一種數據類型預留了64個字段,該表的字段數超過300,記錄數在100萬條以上,也沒有見嚴重影響性能.

            很多時候,數據冗余是提升性能最有效的方法,特別是三個以上的表間聯接,通過數據冗余來改善性能是非常明顯的,同時也減小了SQL的復雜度.

            #42    回復  引用  查看    

            2005-05-09 21:33 by 一川煙草      

            為什么會認為ID不用保留呢?
            如果要針對付款方式做統計,沒有ID,難道就用名稱來統計嗎?
            例如某付款方式曾經叫 牡丹卡(當時工行只有一種卡) 后來增加了牡丹靈通卡,牡丹儲蓄卡,原來的牡丹卡名稱改為牡丹信用卡,但ID不變。
            那么請問贊成不保留id的朋友,怎么統計訂單中付款方式為牡丹信用卡的總金額呢?

            #43    回復  引用  查看    

            2005-05-09 21:42 by 小陸     

            冗余這樣的方式一般都用于提高系統的性能和增強系統的容錯性,并且一般說來,冗余會增加開發的復雜度。在冗余數據之間進行同步是需要耗費精力的,要在開發團體中形成一致的意見,并且要保持后來加入人員認識的統一。這需要嚴明的紀律和充分的交流。如果一個數據只有一個來源,大家的認識很容易一致。如果一個數據要保存在多個位置,則團體的每個人中對一個數據的來源,更新的時候要不要同步,選取的時候到底從哪里取等一些事項上容易產生分歧,極易造成臟數據。
            冗余要有明確的目的,不能貪圖一時之便,否則帶來的可能是麻煩。第三范式是一個正確的準則,也許有時可以違背,但是一定要有一個更加強的準則作為支持,要考慮具體的情況。這個更強的準則,我想應該不是可以省一點事

            #44 [樓主]   回復  引用  查看    

            2005-05-09 22:29 by 聽棠.NET     

            @小陸 :
            現在我現在討論根本不是指你說的冗余,我所指的這種冗余是必須,根本不需要同步不同步的。因為訂單的那些信息具有歷史性。從一點上來說,你說的冗余是另一回事。

            #45    回復  引用  查看    

            2005-05-12 11:42 by 平常     

            1我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
            2
            我也不想,因為下了這張訂單了,而嚴格控制付款條款的刪除功能,這也不合理,憑啥不能刪除了?下個月這個條款確實永遠不會采用了。
            3
            我也不想,付款條款修改后,導致以前所有采用此付款條款的訂單都變成新的條款,那在系統中的訂單如何與手頭的紙張訂單再對應,這肯定也不合理。

            參照(Reference
            參照在數據庫設計中是一個比較復雜的問題,它是實現數據的完整性主要要素之一,詳細論述參考后面數據的約束。

            PowerDesigner中,可對參照完整性進行各項設置,參照的基數從0n,對修改和刪除約束可分別設置為NoneRestrictCascadeSet NullSet Default。由于INSERT包含在UPDATE操作中,因此沒有單獨的INSERT約束。

            約束的不同設置產生不同的效果,以修改為例(刪除相同):
            None
            :父表修改,子表不影響。
            Restrict
            :父表修改,如果子表存在,則出錯。
            Cascade
            :父表修改,如果子表存在,則相應的修改。
            Set Null
            :父表修改,如果子表存在,則相應置空。
            Set Default
            :父表修改,如果子表存在,則相應置默認值。

            #46    回復  引用  查看    

            2005-05-12 11:50 by 平常     

            數據庫的完整性
            數據庫完整性可通過存儲過程、聲明性參照完整性(DRI)、
            數據類型、約束、規則、默認值,以及觸發器來實現。在數據庫內,這些功能各以特有的方式發揮作用。綜合利用這些完整性功能,可以使數據庫靈活,易于管理,而且很安全。
            數據完整性概念分為幾個方面。
            表域完整性
            通過主鍵來強制表的域完整性。
            引用完整性
            利用參照來加強表之間的邏輯關系。
            數值域完整性
            任何輸入的數據在類型和范圍上必須與指定的數據類型相匹配,只有當某列被說明允許NULL值,才允許向該列輸入NULL
            數據庫的性能測試
            生成數據庫之后,應進行數據庫性能測試,以便優化數據庫的設計,因此需要生成測試數據,由于是性能測試,數據的規范性要求不高。通過PowerDesigner可方便地生成測試數據(Generate Test Data),完成性能測試。
            數據的約束
            O-O
            約束
            對父表的INSERTUPDATEDELETE操作沒有限制。
            M-O
            約束
            對父表操作的約束:
            父表的INSERT操作,對M-O約束,父表中間的記錄可以沒有任何約束地添加到表中,因為這種約束中不一定必須有子女。
            父表的鍵值修改操作,只有在子表中其所有的子女對應均做修改后,才能修改,即一般采用級聯更新的方法。
            父表的刪除,父親只有在其所有子女均被刪除或重新分配之后該父親才能被刪除。
            強制對可選(M-O)約束
            O-M
            約束
            父表操作的約束:
            父表的INSERT操作,對O-M約束,一個父親只有當至少當它的一個、子女同時被加入或至少存在一個合法的子女時,才能被加入。
            父表的鍵值修改操作,只有當一個子女被創建或已經有一名子女存在才行。
            父表的刪除,理論上刪除父親是沒有限制的,實際上,刪除主表記錄時,不采用級聯刪除子表的方案,而采用將子表的外鍵置空。
            可選對強制(O-M)約束

            M-M
            約束
            父表操作的約束:
            父表的INSERT操作,可能隨后需要生成子女,即在子表中創建新的行。也可能通過對子表的重新分配來實施完整行限制。
            父表的鍵值修改操作,只有在子表對應的外鍵的值修改成新值時才能進行。實際可能是先創建新的父表紀錄,接著修改子表所有對應的紀錄,使其與父表的新紀錄關聯,最后刪除原父表紀錄。
            父表的刪除,只有在子表中所有相關的行全部刪除或重新分配之后,才能刪除父表中的紀錄,一般對子表也進行刪除操作。
            強制對強制(M-M)約束

            在四類約束:M-MM-OO-MO-O。鍵值的修改可能會改變表之間的關系,而且可能違反一些約束。違反約束的操作是不允許的。具體的應用必須根據實際的要求和商業規則進行適當的選擇。但在設計和開發時,必須考慮所分析的約束。

            #47    回復  引用  查看    

            2005-05-13 01:26 by magic007     

            1、要看開發的這個系統是個什么樣的系統,僅僅是一個OLTP系統,或者還要在系統上進行數據分析和數據挖掘。如果僅僅是一個事務處理系統,則以樓主所說的做法,行得通,否則的話,最好不要那樣做。
            2
            、以我的經驗,數據冗余在開發上更方便一點,效率可能會高一點,但是后期可維護性和擴展性是比較差的。
            3
            、關系數據庫一個核心的理念應該就是關系了,數據關系。設計數據庫,準確的說是設計數據模型,一是保證整個數據模型具有良好的擴展性,也就是說為以后業務的發展,需求的變化提供足夠的可擴展性。開發的方便來說應該是次要的,無非就是多點編碼。
            4
            、在樓主的例子中,我從數據關系上談一下,訂單與客戶之間是很強的耦合關系,沒有客戶,那么訂單就沒有存在的意義。所以肯定是需要主外鍵關聯的。對于付款條款,在業務領域內,對于訂單來說是必須具備的,那么也需要主外健關聯。比如客戶有同名的情況,怎么標識多張相同客戶名的訂單是同一客戶還是不同的客戶?客戶改名了,如何標識改名前的訂單和改名后的訂單是同一張訂單?為了避免在客戶改名后,改名前的訂單的客戶名變成新的客戶名,可以在客戶表中建立組合主鍵,如cust_idcust_seq_id

            #48    回復  引用  查看    

            2005-06-04 17:27 by 小李程序?     

            感覺到有時冗余是有必要的,我相信這里講的冗余并不是為了提高系統的容錯,它也不是我們在這里討論的范疇。我最關心的就是冗余帶來的性能上的提高,因為它極大地減少了在做交集運算的時間。
            況且這種冗余完全可以交個我們的DBA去做,我們只關系他提供給我們的數據即可,至于因為數據冗余可能帶來的不一致,完全可以用觸發器來實現。

            #49    回復  引用  查看    

            2005-06-07 21:45 by shewo     

            你把把客戶的名稱、聯系電話、付款條款名稱等訂單上要求記錄的信息直接COPY到訂單的表中,造成了重復存儲,重復存儲的結果就是數據冗余,冗余的結果很可能就是更新異常,因為有可能你更新了客戶表中更新了客戶的名稱、電話,你必須還要更新訂單中的相應信息,反而造成了效率的下降,如果你疏忽忘記更新這些信息了,結果便是數據不一致

            #50 [樓主]   回復  引用  查看    

            2005-06-08 08:20 by 聽棠.NET     

            @shewo
            老兄啊。你怎么還在講這個理論呢,前面的回復你看了嗎?我文章的主要目的就是寫給你這樣的人看的。
            一般的人都是以為這樣想的,這個誰都知道,我的文章中也指出了,對于象訂單這種客觀存在的東西,不能死板的搬那種理論。
            你說的這種數據不一致,你覺得需要保持嗎?已經成為歷史的訂單,你認為以后因為基本數據的修改,需要全部修改進去嗎?那么歷史訂單怎么辦??客戶會把已經完成的訂單存檔作為備案,你的意思是客戶還要把以前的訂單找出來一個個修改。。最好再理解一下我文章的意思。真沒想到,你什么也沒看懂。

            #51    回復  引用  查看    

            2005-06-13 13:20 by skyworht     

            第三范式要求是屬性不依賴于其它非主屬性。我對編程還沒入門,只是瀏覽過幾個比較正規的軟件。我覺得兩種方法都是可行的,不過是應用的環境要因實而選。聽棠.NET方法對一些數據量較小、應用中改變較為頻繁的數據,比較適用。外鍵引用,對無效標記的方法在與上相反的情況下應用也許更好。

            拋磚引玉,各位指教。

            #52    回復  引用  查看    

            2005-06-13 21:01 by Peter     

            "third normal form" should be used as a guideline to control the database design. I don't think the original design is against "third normal form". To copy extra information to "Order" such as payment term, delivery method etc, I think this is a correct way to do it as the author explained.

            When you look at a design and to determine if it follows "third normal form" rule, there is a "time" factor in it. The original setting such as payment term and delivery method are the default setting, which don't determine every single order.

            Another way to do it is to design a base level table that has a "time" factor it in.

            Just some ideas and I found it's every hard to understand most comments here.

            P.S. There is no right and wrong in relational database design, the only crieria is to test it in a real life situation.


            P.

            #53    回復  引用  查看    

            2005-07-01 23:15 by min     

            學習。。。

            #54    回復  引用    

            2005-08-04 15:54 by tx-zero [未注冊用戶]

            終于看了一半,累死我了,呵呵。
            看到大家都是在討論一個問題,就是碰到樓主的情況,
            1copy保存,還是2,設置標志的問題。

            就我看,還得根據客戶業務的需要而決定。

            我做過一些系統,由于是關系到一些企業內部比較重要的資料。因此,客戶都要求操作要能夠恢復,當然恢復是在一定的條件之下的。但是記錄客戶的操作還是必須的,并且需要記錄用戶操作了什么,改變了什么數據。

            針對我說的這種客戶,我大多會采用,做標志,并且copy的方法。
            呵呵。
            不寫了,寫得太多,別人看得也累,呵呵。

            #55    回復  引用  查看    

            2005-08-05 17:46 by kilnt     

            學院派設計要死人的,維護冗余數據一樣也夠死人,這個要權衡了。

            另:別看啥大系統,很多大系統細節技術實現很爛的,庫結構也很爛。

            #56    回復  引用    

            2005-08-15 16:08 by nwc [未注冊用戶]

            這個問題討論很激烈啊!我沒什么經驗,也想談點看法。
            系統怎么設計?要不要冗余?要多少靈活性?這些都是和用戶需要
            相關的。上面說到條款的改變和訂單的歷史性、一致性問題,既然
            條款經常要改變,為什么不做一個條款改變的歷史記錄表,其中有
            條款不同版本的有效時間段和實際內容,這樣每個訂單都有當時的
            條款內容可查,只不過還是要加一個時間字段。新的訂單就用新的
            條款內容。
            這種靈活性是增加了,不過復雜度也同樣增加了,減少冗余,就要
            增加計算的時間。怎樣在效率與空間上取得平衡還是要看用戶的需
            要了。

            #57    回復  引用    

            2005-08-15 16:39 by nwc [未注冊用戶]

            原來peter說過了,我多嘴了。

            #58    回復  引用    

            2005-09-28 11:01 by 榴彈炮 [未注冊用戶]

            上面的東西太多了,簡單發表一下看法:
            1.
            范式不是籠子,達不達成,要看情況;
            2.
            腦子里沒有范式的人去談上面這條,還是補了課再來;
            3.
            訂單上的數據冗余要看情況,如果要保存訂單的歷史紀錄而紀錄詳細的客戶信息,不算違反第三范式,因為客戶表內的數據與訂單上表的歷史紀錄意義并不相同,tag的方式來記錄歷史的客戶信息更不違反范式,但要看情況而定.因為歷史的客戶信息可能與現有的客戶信息Code/name相同而違反鍵的約束,另外,由于單據要進行EDI,保存詳細的客戶信息更加重要.
            4.
            純數據表(不參與EDI與證據紀錄)要嚴格遵守第三范式,否則數據一致性問題會讓你知道什么叫做"維護"!這個等式用空間換效率來寫太膚淺,應該是用空間+編程錯誤率+維護效率來換執行效率+編程效率.
            5.
            再次打倒那些腦子里沒有范式的變態份子!我已經快被他們的程序煩死了.

            #59    回復  引用    

            2005-09-28 12:45 by luckcp [未注冊用戶]

            我認為樓主說的應該是標準引用,而本身就不應該做成外鍵,所以不違反三范式。
            以訂單為例:有兩個屬性分別是客戶與付款條例。客戶屬性應該用外鍵做,而且盡量使用數據庫的外鍵機制(存在訂單引用的客戶不能刪除,不要設置為級聯刪除)。客戶信息的修改反映到訂單是應該的(一條歷史訂單跟隨客戶名稱的變化而變化對查詢是沒有影響的,況且客戶資料的修改本身就應該謹慎)。付款條例應該做成一個付款標準表(標準引用),訂單存儲的是付款標準表的實際數據項。

            #60    回復  引用  查看    

            2005-11-08 23:37 by 綸巾客     

            我覺得不違背第三范式也是可以的,一般來說,我們會有一張WasteBook表,記錄當時的信息,保存歷史數據。這樣的話,既可以保證數據庫設計的規范,也可以提供靈活性。

            #61    回復  引用  查看    

            2006-05-07 17:22 by 月色瘋狂     

            理論就是理論。要么就對,要么就不對。這個沒有什么可含糊的。
            樓主的問題,實際上是個版本問題。每次條款修改,都會產生一個歷史版本。這個歷史版本是只讀的。并且是不可改變的。可以刪除某個條款,但是歷史是不能刪除的。因為它被引用了。
            只要抽象出歷史版本的概念,就可以解決樓主所說的問題,并且可以不違反3nf
            歸根結底,還是樓主對業務的概念抽象得不對,不是3nf的問題。
            對于類似的問題,都可以通過引入歷史版本的問題。在設計的時候就要考慮是引用對象本身,還是引用對象的歷史版本,不要把概念搞錯了,更不要以此來懷疑3nf

            #62    回復  引用    

            2007-01-30 16:16 by 雨恨云愁 [未注冊用戶]

            個人強烈同意
            上山砍柴去 的觀點

            #63    回復  引用    

            2007-08-28 09:30 by zhanglin [未注冊用戶]

            第三范式在大的應用系統,想完全遵循是不可能的。

            #64    回復  引用    

            2008-06-04 02:58 by solidco2 [未注冊用戶]

            我比較贊同2樓的這種做法。如果你要查找用同樣的條款下的訂單怎么辦?也要復制過來吧。
            那匯總更不用說了。
            我認為數據存入了數據庫,除了錯誤的之外,理論上應該永遠不會被刪除。就像發生過的事無法抹去一樣。你可以把它塵封,但不能把它永遠消除。
            這一點也許是我從自動編號屬性得到的啟示。因為,自動編號產生了#1#2,刪掉#2,再產生也會是#3。這是因為dbms認為這條記錄并沒有消失,只是你無法找回了。
            扯多了,我確實同意你的結論,不得不違背范式,滿足范式的表會很羅索。倒庫的方法我其實用的不多,更多的是啟用字段,或者狀態字段。



            --------------------------------------------------
            嘿嘿: 范式原則是用于指導性地設計數據的存儲結構的,僅僅只是理論。必要的時候是需要反范式,或者容忍一定的數據冗余,使得系統的性能或邏輯清晰性上更好。

            范式是一種基于純粹的從數據存儲量上來優化數據結構的方式,并不是一個非常通用的東西。

            另外:
            “1
            我不想在訂單下達完以后,刪除了某條付款條款,導致這些訂單無法知道真實的付款條款了,這肯定不合理。
             2 我也不想,因為下了這張訂單了,而嚴格控制付款條款的刪除功能,這也不合理,憑啥不能刪除了?下個月這個條款確實永遠不會采用了。

            上述情況,實際上可以考慮采用倉庫性質的數據管理方法:即,對于所有的數據,分為可用與不可用,放在不同的表間,然后可以把其中的數據挪來挪去。

            你說的情況非常現實,從業務角度出發,將數據結構優化為最高存儲效率的是沒有意義的,范式更多是一種指導,而不是原則。
            --------------------------------------------------------

            #65    回復  引用    

            2008-06-04 03:32 by 還是上面那個人 [未注冊用戶]

            不好意思沒有注意已經是幾年前的討論了。
            不過還是順便再提一下,保證是前面討論中都沒有說的:
            一個公司在04年叫河北科技有限公司開始下訂單。記錄了。05年改名為北方科技有限公司,繼續下訂單。他們是一個公司嗎?查找這個公司的全部訂單怎么辦?
            那就是還要記錄一個營業執照號碼。這個營業執照和ID就是等同地位了,為什么不用ID做一個唯一索引

            #66    回復  引用    

            2008-12-11 17:30 by 用版本控制來解決 [未注冊用戶]

            月色瘋狂說的非常對,
            =====================
            理論就是理論。要么就對,要么就不對。這個沒有什么可含糊的。
            樓主的問題,實際上是個版本問題。每次條款修改,都會產生一個歷史版本。這個歷史版本是只讀的。并且是不可改變的。可以刪除某個條款,但是歷史是不能刪除的。因為它被引用了。
            只要抽象出歷史版本的概念,就可以解決樓主所說的問題,并且可以不違反3nf
            歸根結底,還是樓主對業務的概念抽象得不對,不是3nf的問題。
            對于類似的問題,都可以通過引入歷史版本的問題。在設計的時候就要考慮是引用對象本身,還是引用對象的歷史版本,不要把概念搞錯了,更不要以此來懷疑3nf
            =====================

            其實這就和我們用cvssubversion等版本控制系統一樣,應該讓客戶表成為一個時間機器,只能進行查詢和新增操作,而不可能進行真正的刪除和修改操作,我的解決方案是對客戶表加三個字段:IDInt類型),SerialID(自增,標記版本),deletemarkboolean),對客戶表的修改就是新增一條ID相同的記錄,SerialID不同以反映版本,刪除就是標記對應IDdeletemark字段。

            以上方案可以完美的解決樓主提出的問題,邏輯自洽且不違反范式要求。
            同時也能解決
            ======================
            一個公司在04年叫河北科技有限公司開始下訂單。記錄了。05年改名為北方科技有限公司,繼續下訂單。他們是一個公司嗎?查找這個公司的全部訂單怎么辦?
            那就是還要記錄一個營業執照號碼。這個營業執照和ID就是等同地位了,為什么不用ID做一個唯一索引
            ======================
            的問題,因為ID不變。

            大家以為如何?

             

            posted on 2009-06-18 14:16 肥仔 閱讀(4562) 評論(2)  編輯 收藏 引用 所屬分類: 數據庫

            評論

            # re: 數據庫設計之&ldquo;有時不得不違背的第三范式&rdquo;[未登錄]  回復  更多評論   

            用標記來假刪除數據都是,提出這個方式的人的一廂情愿。
            客戶同意嗎?你們真正懂客戶嗎?
            很多時候,這種方式客戶能接受
            但也有很多時候客戶不能接受
            有些時候客戶必須徹底的,永遠的刪除(有些敏感信息客戶在必要的時候必須隨時可以刪除)。
            這個沒有絕對的解決方法。
            有些人說謂范式就是一定要遵從,那是誤認子弟的。
            滿足用戶需求至上。
            那些說維護多么困難的人也是白癡(再整潔的數據庫設計也需要隨著客戶的業務變化而變化,你必須要維護,如果維護那么重要,怎么能體現你對于客戶的價值呢,能一個系統維護是要收費的,幾年后要翻新的,翻新是要賺錢的,連維護都沒有,別人還要你干嘛(除了sap買保險式的維保),連維護都沒有客戶還要翻什么新).

            這些理論都是相對的,事實可以證明是他錯誤的:我沒有用第三范式,客戶一樣認同,系統一樣好維護,我一樣賺到錢了,客戶也通過系統的價值給他帶來好處。當然也可以拿出事實證明他是對的,但這就是一個矛盾體。(其實說實在話,大家搞開發都注重前期的實現吧,至于后期的維護有多少人考慮過,如果沒有考慮,就不要拿維護難來說事)


            從另外一個角度看:
            時間+質量+成本 = 項目的管理維目標,如果關系型數據庫數據范式第一大于項目管理目標的話(第三范式就是在付出這3個代價的,為了換取你那個所謂的維護容易,存儲量小,數據量少,你們都知道:存儲硬件不是問題吧,那實在太便宜了,數據難得維護客戶一般不會說是系統亂的問題吧,你可以說是業務導致數據復雜難的維護,但性能不好(為了第三方式,必然存在大量的聯合查詢,如果數據量大查詢性能不好的話),客戶一定會吊死你的),那不用關系型數據好了。
            2009-08-20 23:39 | 無名

            # re: 數據庫設計之&ldquo;有時不得不違背的第三范式&rdquo;[未登錄]  回復  更多評論   

            冗余這樣的方式一般都用于提高系統的性能和增強系統的容錯性,并且一般說來,冗余會增加開發的復雜度。在冗余數據之間進行同步是需要耗費精力的,要在開發團體中形成一致的意見,并且要保持后來加入人員認識的統一。這需要嚴明的紀律和充分的交流。如果一個數據只有一個來源,大家的認識很容易一致。如果一個數據要保存在多個位置,則團體的每個人中對一個數據的來源,更新的時候要不要同步,選取的時候到底從哪里取等一些事項上容易產生分歧,極易造成臟數據。
            冗余要有明確的目的,不能貪圖一時之便,否則帶來的可能是麻煩。第三范式是一個正確的準則,也許有時可以違背,但是一定要有一個更加強的準則作為支持,要考慮具體的情況。這個更強的準則,我想應該不是“可以省一點事”。
            【轉的】
            2011-06-02 18:20 | kevin
            久久久久久久91精品免费观看| 久久天天躁狠狠躁夜夜不卡| 久久久99精品一区二区| 国产精品成人99久久久久91gav | 青春久久| 久久香综合精品久久伊人| 久久久久亚洲AV无码麻豆| 久久99精品国产一区二区三区| 伊人色综合久久天天| 伊人久久大香线蕉精品不卡| 国产成人久久AV免费| 久久人搡人人玩人妻精品首页| 久久精品国产精品亚洲艾草网美妙| 天天综合久久久网| 久久人人爽人人爽人人片AV东京热 | 亚洲成色www久久网站夜月| 国产精品久久久天天影视| 久久免费国产精品| 亚洲人成网站999久久久综合| 一级做a爰片久久毛片看看| 国产99久久久国产精品小说| 无码人妻久久久一区二区三区| www性久久久com| 久久国产热这里只有精品| 久久91精品国产91| 国产一级持黄大片99久久| 久久久久久av无码免费看大片| 国产免费久久精品99re丫y| 2021久久国自产拍精品| 久久人人超碰精品CAOPOREN| 久久久久99精品成人片试看| 国内精品欧美久久精品| 久久精品国产秦先生| 亚洲欧洲中文日韩久久AV乱码| 99精品国产在热久久| 久久精品国产日本波多野结衣| 美女写真久久影院| 久久精品国产亚洲AV大全| 亚洲国产成人精品无码久久久久久综合| 久久综合亚洲色HEZYO社区| 久久综合九色综合久99|