mysql開發資料庫命名規範問題?

資料庫名 小寫。
表名 前綴_小寫。

那麼欄位名:
我看到一個資料是這麼說的:
一種推薦的命名規則是:在定義資料庫、表、列的時候全部採用小寫字母加下劃線的方式,不使用任何大寫字母。

大家認可么?是這麼操作的么?
雖然大小寫無所謂,我只是想看看最佳的規範。


https://github.com/zhblue/crud


關於資料庫設計中的命名規範問題整理如下:


1、引言

在前面提到過,資料庫設計過程中表、欄位等的命名規範也算是設計規範的一部分,但因為牽涉的內容較多,所以將其單獨列出。不過設計規範更多的是為了確保資料庫設計的合理性、為了項目最終的協調穩定性,而命名規範則更多的是為了確保設計的正式和統一。公正的講,資料庫中表欄位等等以什麼樣的方式命名、取具體什麼名字,並不會直接影響到項目的穩定性,不是說叫黑貓項目就是正常的,叫白貓就運行異常了。

制定規範的直接目的是約束設計行為,最終目的是確保設計的合理統一。規範雖然是有豐富項目經驗的人制定的,但維護的卻不是某個人的意志,而是項目的意志,因為遵守此規範對項目是好的有利的,此規範才有意義。所以規範是為了項目利益最大化而在團隊人員中形成的一種約定(貌似約定的英文單詞Convention本身就有規範的意思),所有參與設計的人員都要遵守此約定,所有參與開發的人員都會依此約定解讀設計。我們約定,所有的主鍵統一命名為id,結果有設計人員違反約定將一個非主鍵欄位命名為id,約定被打破,共識也就被打破,設計人員之間、開發人員與設計人員之間的溝通就出現了隔閡。

設計規範更多的是為了合理,命名規範更多的是為了統一,團隊協作中,統一在某種程度上比局部設計開發的好壞更重要。違反了約定,局部設計開發的再好,反而可能影響到項目整體的穩定協調。

約定優先於配置(Convention Over Configuration)。

在「設計規範」中提到過一些命名規範,也詳細講述了表、欄位的類型、注釋等屬性的設置,為什麼要求主鍵統一命名為id、統一為char(32)類型,為什麼要求浮點型數值統一為decimal類型?我們希望團隊中所有人看到設計成果,一眼就可以明白這個欄位是做什麼的、代表的含義是什麼,可以但不止於見名知意。再者,當前的開發模式,前後端代碼及資料庫文檔、程序文檔、介面文檔等等大都是由工具生成,而其最底層的依據就是資料庫,表、欄位的命名注釋同時會影響到工具生成的文檔、代碼中的類屬性方法甚至是前台頁面的命名注釋,資料庫設計命名的規範關係到整個項目的規範。

命名規範會分四個大模塊來介紹:基本規範、名大小寫、具體規範、特別說明,各大模塊下面有的會有子模塊特別說明。

2、基本規範

A.可用字元

資料庫、表、欄位等所有名稱的可用字元範圍為:A-Z,a-z, 0-9 和_下劃線,除此外不允許使用其它字元作為名稱。資料庫及表名均不允許出現數字,欄位名除非特殊情況不允許出現數字。

在前面介紹關係範式時曾提到過一個破壞範式的例子:平時的多圖片上傳功能,可能只設計一個欄位存儲圖片名稱,這樣欄位值中就會包含多個圖片的名稱,裡面用|或其它符號分隔。像這種情況,其實也可以設計成三五個欄位image_name1、image_name2、image_name3……分別存儲,然後限制可上傳圖片個數,這就是欄位名中可出現數字的特殊情況——雖然也不建議這樣設計或取名。

B.命名方式

資料庫、表、欄位等所有名稱使用英文單詞或英文短語或相應縮寫,禁止使用漢語拼音,且均使用單數名,例如:對存儲客人信息的表命名為customer而不是customers。名稱應該清晰明了,能夠準確表達事物的含義,遵循見名知意的原則。

Oracle表、欄位等名稱統一使用大寫,單詞間用_下劃線分隔;SQLServer資料庫、表等名稱採用Pascal命名法,欄位名稱採用Camel命名法,大小寫字母混排;MySQL資料庫、表、欄位等名稱統一使用小寫,單詞間用_下劃線分隔。至於為何這樣規定,下一個模塊會有詳細介紹。

Oracle相對特殊,通常的操作順序是,先創建資料庫實例,然後創建表空間,然後創建用戶並設定此用戶的默認表空間,最後在此用戶下建表。多數情況下我們都是只建一個實例,然後在此實例下建不同的表空間、不同的用戶,根據不同的用戶來區分不同的庫。關於實例、表空間及用戶的命名方式並無限制,可以採用大小寫混排,也可以只用大寫或小寫,但對於表和欄位,我們要求統一為大寫。

我們要求統一為大寫或小寫的名稱,兩個單詞間用_下劃線分隔,SQLServer使用Pascal或Camel方式命名。這些不僅僅是為了資料庫設計的可讀性,也是為了最終生成代碼的可讀性。這裡簡單介紹下編程中常用的三種類、變數、函數等的命名方式:

a. 匈牙利命名法。由微軟的一位匈牙利程序員Charles Simonyi 提出,相對複雜,首字母小寫,基本原則是:變數名=屬性+類型+對象描述,其中每一對象的名稱都要求有明確含義,可以取對象名字全稱或名字的一部分。匈牙利命名法主要在C或C++這種面向過程的程序語言中使用,如果用在Java、C#這種面向過程的語言中就很彆扭。

不過自己在寫Web前端頁面或腳本時,借用了這種命名方式,form表單中涉及的常用HTML標籤不外乎如下幾種:label、text、button、submit、password、textarea、radio、checkbox、select等,那我在給表單元素命名或者說是給id或name賦值時,就會將元素類型做前綴,例如用戶名輸入框為textName、性別單選按鈕名為radioGender。這樣做的好處是我在編寫腳本時,根據id或name名稱一眼就可以看出這個表單元素是什麼類型。在修改頁面中初始化表單數據時我可以直接遍歷表單元素、根據元素名稱判斷出元素的類型進而採用適當的賦值動作,而不用逐個選擇元素去賦值。

在http://ASP.NET編程中,如果使用微軟的伺服器控制項,在命名時我會用控制項類型做名稱後綴,例如Name_TextBox、Gender_RadioButtonList等。之所以不再將類型做前綴,一來是VisualStudio本身默認的伺服器控制項命名方式即時如此,控制項類型做後綴;二來是因為伺服器控制項的類型名稱太長,而自己又不願用縮寫,因為沒必要,VisualStudio的提示功能強大,後綴的長度不會影響到編程速度。

b. Camel命名法。即駱駝式命名法,首字母小寫,採用該命名法的名稱看起來就像駱駝的駝峰一樣高低起伏。Camel命名法有兩種形式:

第一種是混合使用大小寫字母,例如englishName、fartherCode。在Java中,屬性名和方法名一般都採用這種命名方式,在C#中只有屬性名採用這種命名方式,我們在前面也規定,SQLServer中欄位的命名也採用這種方式。第二種是單詞之間加下劃線,例如english_name、farther_code。我們在前面規定,Oracel和MySQL表、欄位的命名都採用這種方式,不過我們要求Oracle全部使用大寫字母,MySQL全部使用小寫字母。再者,無論是在Java還是C#,甚至是在JavaScript中,所有的常量,都使用這種命名方式,但和Oracle表欄位的命名方式一樣要全部使用大寫字母,比如前面的設計規範中介紹數據字典表時,字典類型、字典項的編碼和文本信息需要即時獲取,以往的習慣在程序中建立一個常量類,所有用到的字典數據在裡面用常量標明,這時常量的命名方式即是如此。

c. Pascal命名法。即帕斯卡命名法,與Camel命名法類似,不過是首字母大寫。在C#中,類名和方法名一般採用這種命名方式,在Java中類名一般採用這種方式。在前面也規定,SQLServer中資料庫、表的命名也採用這種方式。

除資料庫的設計外,不同編程語言、前端HTML標籤、JavaScript腳本、樣式等等部分都會涉及命名的問題,如果細細整理,項目開發中每個子模塊的命名規範都夠再出一份長篇文檔的。這裡只簡單介紹下三種常用的命名方式,其它部分的命名方式只是一提,重點還是在資料庫的命名規範上。前面說過多次,程序、文檔甚至前端頁面有大部分通過工具自動生成,只有資料庫嚴格按要求來命名,才能根據不同的編程語言編寫不同的代碼模板,統一控制生成部分各處的命名方式。比如,我們要求在MySQL資料庫中,表名都使用小寫,單詞間用下劃線分隔,交易記錄表名稱為trade_log,那可以設定生成規則,對應生成的實體類名就是TradeLog,對應生成的Dal層就是TradeLogDal,對應的Service名就是TradeLogService,等等。可如果設計沒有規範、不統一,那文檔生成規則、代碼生成規則、程序編寫規則等等也就無法統一制定了。

C.長度限制

關於各種資料庫管理系統(DBMS,Database Management System)本身對錶、欄位等名稱的長度限制如下:

https://pic4.zhimg.com/v2-cf4ad6d3c6ca2534d2e1b7b8b7193edf_b.png

以上是從網路整理而來,Oracle、SQLServer及MySQL的限制長度親自測試過。但也有說因為資料庫和表的名字可能對應於目錄和文件名,故而伺服器運行的操作系統可能強加額外的限制。不過除了Oracle的限制長度過短外,其它的一般不會被超出。我們希望名稱儘可能詳細準確的表達事物含義,但如果過於冗長,就會給操作及後面的程序編寫帶來諸多不便。

D.單詞縮寫

自己以往設計資料庫時,經常頭疼於表、欄位的命名,一來找不到好的單詞去表述,二來有時可能涉及多個單詞,導致名稱過長。欄位名過長帶來的不便有限,最終影響的不過是程序實體類中的一個屬性,可如果表名也過長,就比較麻煩了,生成的程序各層間針對此表的類名、變數名都可能受到影響,給後期的編寫帶來很大不便。使用單詞縮寫又拿不準,找不到合適的縮寫方式。這裡建議當表名超過15個字元、欄位名超過20個字元時就應該嘗試用單詞縮寫重新命名,如果名稱長度在此之內,原則上講則儘可能不用縮寫以使表述具體清晰,表、欄位最終的名稱長度要嚴格控制在30個字元以內。關於單詞縮寫規則如下:

a. 如果可以在字典里找到一個詞的縮寫,就用這個做為縮寫,比如:Monday=Mon、December=Dec ,可在此網站下查找到一些英文單詞的縮寫:http://shortof.com/;

b. 可以刪除單詞母音(詞首字母除外)和每個單詞的重複字母來縮寫一個單詞。比如:Current = Crnt、Address = Adr、Error = Err、Average = Avg;

c. 對於主從表,如果主表名稱沒有縮寫而從表的名稱需要縮寫,則從表名稱從第二個單詞開始縮寫,第一個名詞儘可能和主表保持一致。比如企業基本信息表名稱為enterprise,則企業訴訟表enterprise_litigation可簡寫為enterprise_ltg,企業證書表enterprise_certificate可簡寫為enterprise_crt。最終的資料庫表及由資料庫表生成的程序在集成開發環境(IDE,Integrated Development Environment )中是按名稱排列的,這樣做是為了讓相似功能的表、類文件排列在一起,方便開發者操作。

更詳細的單詞縮寫規則介紹可以參考文檔末尾的參考文獻。

3、名大小寫

理想情況下所有關係型資料庫對於表名、欄位名、欄位內容等大小寫的處理會有個大一統的方式,比如要求所有都是大小寫敏感的,可實際的情況卻是,不同的資料庫及同一資料庫在不同的操作系統下對大小寫的處理都是不同的。以往筆記中記錄的第一次遇到資料庫處理大小寫的問題是,做的一個登錄頁功能,測試人員發現輸入用戶名MengXianzhi或mengxianzhi均可以正常登錄,但資料庫用戶表裡只有一條用戶名為MengXianzhi的記錄,當時用的是SQLServer資料庫。

A.編碼和字元序的介紹

在前面介紹資料庫編碼時曾經提到,如果使用MySQL Workbench創建新的資料庫,會要求選擇Collation。Collation的字面意思是字元序,用於指定數據集如何排序、及字元串間的比對規則。可字元本來是不分大小的,這樣對字元的&>、=、&< 操作就需要有個字元序的規則。Collation做的就是這個事情,你可以對錶進行字元序的設置,也可以單獨對某個欄位進行字元序的設置,優先順序從高到底可分為四種:伺服器層、資料庫層、表層、欄位層,真正決定性因素是在欄位層,如果沒有指定則默認從上一層繼承過來:欄位層繼承表層,表繼承資料庫層,資料庫層繼承伺服器層,伺服器層則需要設置,如果不設置默認為latin1_general_ci。

平時我們說的設置MySQL編碼為gbk、gb2312、utf8或lantin等指的是字元編碼,也就是Character Set。當表的Character Set 是lantin1時,若欄位類型為nvarchar,則欄位的字符集自動變為utf8。

可見資料庫、表、欄位的Character Set可逐級覆蓋,這有點像上面說的四種字元序設置方式間的優先順序關係。本規範中建議資料庫統一設置編碼為utf8,不僅僅是為了應付資料庫間導入導出過程中、因編碼格式不統一而導致的惱人的亂碼問題,也是因為utf8是一種萬國碼(Unicode)。軟體的國際化是大趨勢 , 而Unicode 是國際化最佳的選擇。在MySQL中有兩個支持 Unicode的Character Set:第一個是UCS2,使用 16 bits 來表示一個 Unicode字元;第二個是utf8,使用 1~3 bytes 來表示一個 Unicode字元。

那字元編碼(Character Set)和字元序(Collation)之間的關係是什麼呢?

每個Character Set 會對應一定數量的 Collation,在MySQL命令窗口中輸入Show Collation;命令可以查看到所有字元序及其所屬的字元編碼列表:

https://pic4.zhimg.com/v2-65271c7142d84f3c4270804b67394ae3_b.png

同一個Character Set的不同 Collation 的區別在於排序、字符集對比的準確度以及性能,這裡的準確度是指相同兩個字元在不同國家語言中的排序規則可能是不同的 ,性能是指排序以及比對速度。例如:utf8_general_ci 在排序的準確度上要遜於 utf8_unicode_ci, 當然,對於英語用戶應該沒有什麼區別,但性能上要略優於 utf8_unicode_ci,例如前者沒有對德語中? = ss的支持。而 utf8_danish_ci 相比 utf8_unicode_ci 增加了對丹麥語的特殊排序支持。

Collation名字的規則可以歸納為兩類:&_&_&以及&_Bin。CI 是Case Insensitive的縮寫, CS是Case Sensitive的縮寫,即指定資料庫對大小寫是否敏感。MySQL中Character Set對應的Collation多是CI的,CS這種校驗字元已經逐漸被淘汰,gbk、gb2312、utf8等編碼的所有Collation沒有一個是CS的。Bin表示用二進位存儲數據,用編碼值進行比較,區分大小寫。

在上面的截圖中也可以看到,gb2312編碼默認的Collation是gb2312_chinese_ci、gbk編碼默認的Collation是gbk_chinese_ci、utf8編碼默認的Collation是utf8_general_ci。按本文檔中的規範,建議所有編碼統一設置為utf8,如果不單獨設置Collation,則按默認的utf8_general_ci,欄位值是不區分大小寫的。

那在字元序為CI的情況下,如何在執行SQL查詢時區分欄位值的大小寫呢?假設用戶表user中有兩個用戶:MengXianzhi和mengxianzhi,當我們執行如下查詢時會得到兩條記錄:

select * from user where user_name = "MengXianzhi";

如果要區分大小寫,有下面兩種方式可以精確查詢:

select * from user where binary user_name = "MengXianzhi";
select * from user where user_name = binary "MengXianzhi";

推薦使用第二種查詢方式,這樣可以保證當前欄位的索引依然有效,而第一種會使索引失效。其實個人更傾向於建議統一設置資料庫默認的Collation為utf8_bin,也就是對大小寫敏感。程序中針對資料庫欄位內容的比對查詢處處都是,英文內容存儲也處處都有,如果所有相關查詢語句都加binary關鍵字,太過麻煩,不如在資料庫中統一設置,這樣也不會出現在本章節開頭所描述的問題了。

如果不想在資料庫中統一設置,也可以只針對錶、欄位單獨設置,但非常不建議如此,因為這會導致局部配置和全局配置相悖 。一直堅持規範、約定、配置等儘可能採用大一統的方式,除非不得以。開放局部配置會導致配置的多樣性,不利於統一管理維護,不過下面還是會簡單介紹下局部配置的方法。

B.編碼和字元序的設置

這部分會分別對比MySQL、SQLServer、Oracle三種關係型資料庫的字元編碼和字元序配置,先從MySQL開始。

在MySQL中,自己沒有找到從伺服器層面直接配置Collation的方法,但是資料庫、表及具體欄位設置Collation的方法都有。再就是在PD中未能找到全局設置Collation的方法,只找到了具體到某一欄位設置的地方。截圖如下,最後一張是PD中對某一具體欄位進行配置的方法:

https://pic4.zhimg.com/v2-fc3ffc761b80903b2edf63a29e3dbb3b_b.pnghttps://pic2.zhimg.com/v2-6e55b0cdc41740f8af78c14d454fc6dd_b.pnghttps://pic1.zhimg.com/v2-50e80eb394d31a0e61c4ea191134127c_b.pnghttps://pic4.zhimg.com/v2-408cea09eefee5e5f0490d196ebebb27_b.png

如果要直接更改某一個資料庫的Character Set或Collation可以在MySQL Workbench中做如下設置:

https://pic2.zhimg.com/v2-6d876bdf6ce4825cc17ba3fbb6d54d0d_b.pnghttps://pic4.zhimg.com/v2-f4b3f32aac9b6218814ea05c761d0e5b_b.png

其實Character Set和Collation本就是一體的,所以其實都是在這一個地方設置,兩種選項對應的SQL語句就是:

ALTER SCHEMA `bsctelmed` DEFAULT CHARACTER SET utf8 ;
ALTER SCHEMA `bsctelmed` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_bin ;

在SQLServer 2008中,只找到了從資料庫層及具體欄位層面直接配置Collation的方法,但是從表層面中的配置卻沒有。和MySQL一樣,在PD中未能找到全局設置Collation的方法,只找到了具體到某一欄位設置的地方。截圖如下,最後一張是PD中對某一具體欄位進行配置的方法:

https://pic2.zhimg.com/v2-cfb3c140419ac6f2f47a64b2275e13b9_b.pnghttps://pic4.zhimg.com/v2-b079e10d3aa4b6acf56856dd3cb1bc5b_b.pnghttps://pic2.zhimg.com/v2-1d8e21cff0712599547171021015ec49_b.png

如果想查看SQLServer的版本、字元序等相關信息也可以用如下SQL語句:

SELECT
SERVERPROPERTY(N"Edition") AS Edition,
SERVERPROPERTY(N"ServerName") AS ServerName,
SERVERPROPERTY("ProductVersion ") AS ProductVersion,
SERVERPROPERTY("ProductLevel") AS ProductLevel,
SERVERPROPERTY("ResourceVersion") AS ResourceVersion,
SERVERPROPERTY("ResourceLastUpdateDateTime") AS ResourceLastUpdateDateTime,
SERVERPROPERTY("Collation") AS Collation;

直接在SQL Server Management Studio 圖形化界面中更改SQLServer的字符集可能會出現問題:

https://pic2.zhimg.com/v2-6e2f49813d7f86fb52efa1a8f8b6cb85_b.png

這時可通過如下更改語句進行更改:

https://pic1.zhimg.com/v2-2675ff53fb17c0a54f7ea0970beb1148_b.png

ALTER DATABASE HealthManagement COLLATE Chinese_PRC_CI_AS

在Oracle中貌似沒有Collation的概念,又或者是換了另外一個概念來進行類似的設置?在PD中具體到表欄位的Oracle選項卡中也沒有字符集相關的配置:

https://pic2.zhimg.com/v2-129fc7359049f2f420f9029f0d3d6071_b.png

Oracle中默認是嚴格區分欄位內容大小的,如果不想對大小寫進行區分可以使用Lower()或Upper()函數來達到目的,也可以使用NLSSORT()函數,覺得這個函數就和MySQL中的Collation設置所達到的效果相似。如下三個SQL語句所達到的效果是一樣的:

select * from user where user_name = "MengXianzhi" COLLATE Latin1_General_CI_AI;
select * from user where Upper(user_name) = Upper("MengXianzhi");
select * from user where NLSSORT(user_name,"NLS_SORT = Latin_CI") = NLSSORT("MengXianzhi","NLS_SORT = Latin_CI");

但是不清楚上面第三種寫法,如果不是精確查詢,而是模糊查詢,用like關鍵字,查詢語句如何下,嘗試下面的寫法,好像不起作用:

select * from user where NLSSORT(user_name,"NLS_SORT = Latin_CI") like NLSSORT("Meng","NLS_SORT = Latin_CI")+"%";

Oracle9i之前,中文是按照二進位編碼進行排序的,而在Oracle9i中新增了按照拼音、部首、筆畫排序功能,使用方法如下:按漢字拼音排序:

SELECT * FROM USER ORDER BY NLSSORT(user_name ,"NLS_SORT = SCHINESE_PINYIN_M")

按漢字筆劃排序:

SELECT * FROM USER ORDER BY NLSSORT(user_name ,"NLS_SORT = SCHINESE_STROKE_M")

按漢字部首排序:

SELECT * FROM USER ORDER BY NLSSORT(user_name ,"NLS_SORT = SCHINESE_RADICAL_M")

注意,我雖然嚴格測試過MySQL、SQLServer和Oracle三種不同關係型資料庫針對CharacterSet和Collation設置的區別,但對於同一資料庫的不同版本間的區別卻未深究。各種關係型資料庫總是在不停升級,某些升級可能會導致新舊版本間差異巨大 ,而本文檔中所述細節又甚多,所以具體到實際情況,某些地方出現不同也很正常。

C.由此引出的亂碼問題

Character Set和Collation並不僅僅影響到資料庫存儲內容的大小寫敏感問題,還會影響到資料庫操作中常見的亂碼問題。這裡既然提到了,所以簡單講下。

以往負責的項目較為雜亂,所以對各種常見關係型資料庫多有接觸,就自己的經驗,亂碼問題出現最多的是MySQL資料庫,尤其是早期版本的MySQL,其次是Oracle,SQLServer當然也有,但相對少。亂碼問題可以分為以下幾種:

a. 不同類型的關係型資料庫間、數據互相導入導出,導致的中文數據亂碼。

比如將MySQL中的數據導入到SQLServer,將SQLServer中的數據導入到Oracle。這種情況其實相對少見,因為一般數據操作都是在同一類型的資料庫間進行。遇到這種情況時,數據間的導入導出一般都有中間過程,比如先從源資料庫中將數據導出成CSV文件,然後再將CSV文件導入到目標庫。又或者是,藉助目標資料庫的管理工具,直接連接源資料庫進行導入。也有將源資料庫中的數據導出成SQL文件,然後對SQL文件進行一定更改後在目標資料庫中執行的。

b. 類型相同、版本不同的關係型數據間的數據導入導出,導致的中文數據亂碼。

c. 類型相同、版本相同的關係型數據間的數據導入導出,導致的中文數據亂碼。

d. 針對Oracle,客戶端版本和服務端版本不同所致。客戶端的版本比較新、而服務端比較舊,或者是客戶端為32位的而服務端是64位等箸。

e. 主要也是針對Oracle,客戶端和客戶端所在操作系統不協調、服務端和服務端所在操作系統不協調。比如操作系統為32位,但下載的客戶端卻是64位的。

f. 針對程序,官方管理工具操作資料庫查詢沒有問題,但是程序訪問資料庫查詢出的中文卻是亂碼。

中文亂碼問題在各種資料庫的操作中、在種程序語言各種項目的開發中時常出現,針對以上種種我們建議:

a. 安裝及操作資料庫時,編碼相關的默認設置,除非有把握,否則不要隨意更改;

b. 項目開發環境、測試環境、模擬環境、真實環境、線上環境的操作系統及資料庫等儘可能統一版本統一配置,選擇和操作系統相匹配的資料庫版本;

c. 針對Oracle資料庫,客戶端和服務端儘可能統一版本,儘可能選擇和操作系統相匹配的客戶端及服務端版本;

d. 在資料庫日常操作過程中均使用官方的管理工具,或直接在命令行中操作;SQLServer不用說,MySQL我們建議使用MySQL Workbench,Oracle我們建議使用SQL Developer;

e. 如果現實情況不方便或不允許達到以上要求,或者雖然按以上要求操作配置資料庫後依舊出現亂碼問題,那就根據實際情況網路搜索尋求相應解決方案。

遇到具體問題時刻記得Google是第一位的,僅這一項就可以幫我們解決99%的問題。我們的分析討論建議更多的是為了全面了解問題本身,但遇到具體問題如何解決,仍舊要靠自己思考、靠Google的智能搜索。下面的截圖來自於以往筆記,和某一亂碼問題的交鋒:

https://pic1.zhimg.com/v2-6282fee2ad7a88971a5c945f0886524c_b.png

D.表名欄位名等大小寫

上面講字元序的大小寫敏感,針對的都是資料庫表欄位值或者說是欄位對容,而對於資料庫名、表名、欄位名、變數名、執行目錄名等(在執行SQL查詢時)的大小寫敏感呢?

在Linux下MySQL的資料庫名、執行目錄名、 表名、表的別名、變數名默認是嚴格區分大小寫的,資料庫名大小寫敏感不可改,執行目錄名大小寫敏感可參數調配(lower_case_file_system),表名大小寫敏感也可參數(lower_case_table_names)調配,但不確定這個參數是否影響表別名及變數名的大小寫敏感。列名與列的別名在所有的情況下均是忽略大小寫的,也不清楚可否參數調配。

MySQL在Windows下資料庫名、執行目錄名、表名、表的別名、變數名、列名、列別名等默認都不區分大小寫。

用root登錄伺服器修改 /etc/my.cnf配置文件,在[mysqld]節點下,加入一行: lower_case_table_names=1 可以另其不再區分表名大小寫。而在 Windows系統下, lower_case_table_names參數預設設置即為1,即不區分表名大小寫。

在SQLServer中自己測試的結果是,資料庫名、用戶名、表名、表別名、列名、列別名默認在執行SQL查詢時均不區分大小寫。SQLServer版本為2008 R2。

https://pic4.zhimg.com/v2-edfb67dc409b837b8b41cfec8f0fc037_b.png

在Oracle中自己測試的結果是,實例名、表空間名、用戶名、表名、表別名、列名、列別名默認均不區分大小寫。Oracle為Linux版本,11.2.0.4。

https://pic3.zhimg.com/v2-f5b04cbab90c2e0e4e7bd7084ebec9ee_b.png

這樣整理之後,如下表格:

https://pic3.zhimg.com/v2-fe90b57872fe5b1c606f2a127187e25a_b.png

內容中的是否表示默認情況下是否大小寫敏感,括弧中的(可)表示可參數調配。空白部分表示不確定,或者沒有這一項。

SQLServer和Oracle 、MySQL(Windows系統下)雖然同樣默認對錶名、欄位名等不區分大小寫,但不同的是Oracle及MySQL處理的更嚴謹。通過SQL*Plus、PL/SQL Developer或SQL Devloper在Oracle中建表,默認會自動將表名轉換成大寫後再寫入資料庫。 在Windows系統中,默認情況下,建表時MySQL會強制要求所有表名和列名均為小寫。SQLServer雖然在執行SQL查詢時不區分表名、列名大小寫,但在命名及在可視化管理工具中顯示時卻又區分大小寫。也有另外一種可能,目前我測試用的Oracle及MySQL版本比較新,則SQLServer則較舊,最新版的SQLServer或許已經沒有這種問題。

https://pic3.zhimg.com/v2-d742875c144bb15782fa4efcfff8b4a6_b.png

前面說通過SQL*Plus、PL/SQL Developer或SQL Devloper在Oracle中建表,默認會自動將表名轉換成大寫後再寫入資料庫。但實際上Oracle是可以支持大小寫混排的命名方式的,但前提是要在表名外面加雙引號。

仔細查看過,使用PD設計針對Oracle的PDM,如果你的表名全部大寫,那PD在生成SQL建表語句時不會在表名外面加雙引號,可如果你的表名是大小寫混排的,那PD在生成SQL建表語句時會自動在表名外加雙引號,保留這種大小寫混排的命名方式。其實不光是創建表,在Oracle中創建觸發器、序列時也是如此,名字不加引號就不會區分大小寫,加上引號就會區分。

不建議在Oracle中使用大小寫混排的命名方式,原因有很多:

a. 當你使用Oracle SQL Developer工具查看錶時,點選「詳細資料」選項卡,可能會報錯:執行請求的操作時遇到錯誤,ORA-00904:"STATUS":invalid identifier。網上搜到ORA-00904錯誤原因和Oracle建表時表名大小寫有關,但不清楚和Oracle版本有沒有關係。

b. 如果表列名都區分大小寫,那在建立查詢時表名和列名都應該帶有雙引號,會給後面程序的編寫帶來麻煩。如果使用Hibernate框架,那其生成的查詢是不會帶有雙引號的,會出現無法找到表或視圖的錯誤。

c. 使用PL/SQL Developer工具可視化地進行表的刪除等操作時,後台採用的是不帶雙引號的表名,也會出現無法找到表或視圖的錯誤。這時只能採用類似 drop table "tableName" 的語法,在SQL*Plus或PL/SQL Developer手工刪除或修改表。

我們在基本規範中為什麼要求MySQL的資料庫名、表名、列名等統一為小寫,Oracle中的表名、欄位名等統一為大寫,正是基於以上原因。我們希望藉此規定,將命名大小寫規則統一,儘可能的讓資料庫設計不要在名稱大小寫這個問題上多出不必要的麻煩。

這裡順便一提,在PD中可以將PDM中的表名或列名統一轉換成大寫或小寫,菜單Tools——Model Options——Naming——Convertion——Table或Column中進行設置。

E.針對大小寫合理建議

個人認為Oracle資料庫對錶名、欄位名、欄位內容等大小寫敏感的默認處理是最合適的,在執行SQL查詢時不區分表名、表別名、列名、列別名的大小寫,但嚴格區分欄位內容的大小寫。也正因此,我們在基本規範中建議在Oracle資料庫的設計過程中表、欄位等的名稱統一使用大寫,單詞間用_下劃線分隔。

我們在基本規範中建議,MySQL資料庫、表、欄位等名稱統一使用小寫,單詞間用_下劃線分隔。同時,我們建議在MySQL資料庫中將Character Set設置為utf8、將Collation設置為utf8_bin,並在資料庫配置文件中設置lower_case_table_names=1,當然,Windows系統中默認就是此種設置,無需再做更改。

我們建議在SQLServer中將排序規則設置為Chinese_PRC_CS_AS,其默認為Chinese_PRC_CI_AS,因為SQLServer資料庫不用考慮部署在不同系統的問題,所以不建議更改除此外的其它編碼、字元序相關的默認設置。我們上面也說過SQLServer雖然在執行SQL查詢時不區分表名、列名大小寫,但在命名及在可視化管理工具中顯示時卻又區分大小寫,為了查看方便所以我們在「基本規範」中要求SQLServer用Pascal的命名方式。

在「名大小寫」這個章節,更多的不是制定規範,而是在講解前面的「數據編碼」、「基本規範」等模塊中列出的一些規範制定的原因。在這裡詳細講解了MySQL、SQLServer、Oracle三種資料庫的編碼、字元序相關的配置說明以及表名、欄位名、欄位內容等大小寫敏感的控制處理等。

4、具體規範

A.關於資料庫的命名

對於資料庫的命名不做特別要求,簡單明了即可,這裡主要注意在一個大環境中相似項目的資料庫命名,最好有明顯區分。

這裡順帶一提,互聯網公司的資料庫一般分為五個環境:

a. 開發環境(Development Environment)。開發可讀寫,開發人員可以修改表結構,可以隨意修改其中的數據;但是需要保證不影響其他開發同事。

b. 測試環境(Test Environment)。開發可讀寫,部署的測試系統訪問此庫,代測試人員使用。

c. 模擬環境(Simulation Environment )。 開發可讀寫,通過web平台,發起上線請求時,會先在這個環境上進行預執行,這個環境也可供部署上線演練或壓力測試使用。

d. 線上從庫(Real Environment)。 只讀,會實時從線上資料庫同步,不允許修改數據,不允許修改表結構。供線上問題查找,數據查詢等使用。

e. 線上環境(Online Environment)。開發人員不允許直接在線上環境進行資料庫操作,如果需要操作必須找資料庫主負責人,並做相應記錄。

在這些環境中,一定要做到許可權劃分明確,讀寫帳號分離,並且有辨識度,能區分具體業務。例如用戶名w_wap、r_wap 分別表示對wap資料庫進行讀、寫的帳號。

做企業內部應用系統,要求不是特別嚴格的話,沒有模擬環境和線上從庫。而且通常情況下,線上環境的庫在客戶那邊,開發測試的環境在公司這邊,兩邊還不能互通,有時不得不駐場開發直接連接線上環境。但是對於線上環境的直接操作是非常危險的,且容易導致線上環境和開發測試環境表結構的不同步,這個一定注意。客戶那邊應該用許可權嚴格限制對生產環境訪問的人員,開發人員自己這邊要時刻做好數據備份工作,並提前準備好數據出現意外更改或丟失情況的應對措施。同時,在現場開發,針對線上環境的更改要實施同步到公司的開發環境中。線上線下的所有更改,都要經過資料庫主設計師的審核同意。

我們建議,如果可以控制的話,則在不同的資料庫環境中統一表空間名、資料庫名等,甚至是資料庫訪問的賬號名、許可權也可以統一,這樣在部署項目時,配置文件則無需再做過多更改,不同資料庫環境間有表結構或數據的移植時也可避免出現不必要的問題。在對這些環境的資料庫進行備份時,建議在備份文件名中加上前綴和備份時間,以防混淆,比如備份開發環境的資料庫可命名為:DevelopmentEnvironment201703271149。這些都是非常細節的地方,有點吹毛求疵,不做強制要求。

B.資料庫功能塊概述

在前面「設計規範」——「基本原則」——「高級功能」中提到過,現有的開發模式,資料庫只用來做數據存儲。一直堅持業務相關的部分都由程序處理,不到不得以的情況下不要在資料庫中建存儲過程、觸發器、函數、序列甚至是視圖等,儘管如此,這裡還是會簡單介紹下這些高級功能使用時的命名方式。下面的表格列出了資料庫所涵蓋常見功能元素的英文名稱及縮寫:

https://pic1.zhimg.com/v2-10682d031e96351714599360d8371674_b.png

有建議,除表和表欄位外,其它功能塊在命名時均要加英文縮寫前綴。但就個人意見,除視圖外,其它部分加不加前綴不太重要,視圖加前綴是為了在執行查詢時和表區分開,而存儲過程、函數、約束等,我們一眼即可看出它是什麼,更何況在可視化管理工具中,這些功能塊本來就是各自獨立展示的。所以本規範中不強制要求在這些功能上加前綴,但如果要統一加的話,建議使用上圖表格中的英文縮寫。

C.關於數據表的命名

關於表的命名,TB這種前綴是毫無意義的,本來就是一個表,為什麼還要說明?這也是我上面不建議在其它功能塊中加前綴的原因。如果表格數量較少,後期項目擴展升級的可能性不大,也沒有必要加其它前綴。但有時規模相對龐大、業務邏輯相對複雜的項目,表格數量多到一定程度,在可視化管理工具中查閱瀏覽不太方便,這時,根據業務或功能對表格進行分類,加前綴也就有必要了。個人感覺是50張表內的資料庫,加前綴意義不大,超過100張,則很有必要加前綴。而且我們要求,為了不給後期代碼生成造成非必要麻煩,如果要給表加前綴,則所有表均要有前綴,不要出現有些表有、有些沒有的情況。

表前綴主要是為了區分不同功能的表,而非解釋表的功能,表的功能由表名來解釋。前面要求表名的長度要控制在30個字元以內,在此前提下,為了儘可能不影響表的命名,表前綴應該越短越好。我們建議表前綴控制在兩個以內。具體表前綴添加規則建議如下,括弧內的單個大寫字母表示要添加的前綴。這裡以Oracle資料庫為例,具體表名、前綴的大小寫根據實際資料庫參照「命名規範」——「名大小寫」章節的說明:

a. 系統表(S_):System,系統配置相關的基本信息表。系統用戶表(S_USER)、系統角色表(S_ROLE)、系統菜單(S_LINK_MENU)、操作日誌(S_OPERATION_LOG)、登錄日誌(S_LOGIN_LOG)、系統字典(S_DICTIONARY)、系統字典類型(S_DICTIONARY_TYPE)等。

b. 字典表(D_):Dictionary,非系統字典外的字典表。在「設計規範」——「相關注釋」——「字典欄位」中提到過字典表的定義,除了資料庫中的通用字典表,還有一些常見表,比如地區表(D_REGION)、ICD編碼(D_ICD)等,也是一種字典表,這裡的D_前綴即加在這類字典表名前面。

c. 中間表(R_):Relationship,多對多關係中間表。具體命名方式建議為:R_主表名_從表名,在多對多關係中其實不分主從表,這裡我們規定核心表為主表,另外一個為從表。比如用戶角色關係中,用戶表(S_USER)為主、角色(S_ROLE)表為從,那中間表就命名為R_USER_ROLE。當中間表名超長時,則根據實際情況縮寫主從表名,建議優先縮寫從表表名。

d. 業務表(B_):Business,核心業務涉及的基本信息表。這裡的業務是非系統配置業務相關的,比如登錄、註冊、許可權這些業務涉及的表都是和系統配置相關的,前綴應該是S_,而非B_。比如在線商城的項目中訂單業務涉及的表即是核心業務表,會診系統中會診單業務涉及的表即是核心業務表,如果項目龐大,涉及業務較多,可以在B後面繼續加單字母區分不同的業務,BA_、BB_、BC_……,沒必要非得和某個英文對應,只是個代號,和項目組的人員說明即可。

表名前綴的說明如上,已經足夠明確,除此外還應該避免無謂的表格後綴。比如存儲客戶信息的表直接命名為Guest而非GuestInfo,存儲航班信息的表直接命名為Flight而非FlightList。還有命名表時,一律使用單數形式。例如,使用 Employee,而不是 Employees,總之,表的命名應該簡單明了。

D.關於表欄位的命名

a. 所有表中的主鍵統一命名為id,主鍵統一使用UUID,類型統一為char(32)。 不建議使用複合主鍵,即便是在多對多關係的中間表中,個人還是建議用單獨的欄位做主鍵,複合欄位加惟一約束。

b. 所有的表欄位中,除外鍵,其它欄位名都無需刻意加前後綴,也不要在欄位名前出現表名。這裡的外鍵是廣義上的外鍵,不僅包括從表引用主表主鍵的外鍵欄位,還包括存放主表相應關鍵信息的擴展欄位。

比如病人表(Patient),主鍵就是id而不是pateint_id,名稱就是name而不是patient_name。但對於外鍵,比如其它表引用Patient表的主鍵那就是patient_id,對應Patient表的name欄位那就是patient_name。如果一個表中有多個外鍵(欄位)同時引用(對應)一張表的同一個欄位,那再用其它標識,比如在「設計規範」——「基本原則」——「主鍵外鍵」中提到的會診單申請表中會診發起醫院(sender_hopital_id)和會診接收醫院(receiver_hospital_id)。

在前面的「設計規範」——「基本原則」——「主鍵外鍵」和「設計規範」——「約束控制」中有提到主鍵欄位和外鍵欄位的命名 ,這裡再次做以上說明。另,PD中在由CDM轉換成PDM時,會自動根據引用關係在從表中添加外鍵欄位,可以自定義外鍵名稱的命名規則:

https://pic1.zhimg.com/v2-5506f2fd741969bc5109166d53025a70_b.png

c. 在前面的「設計規範」——「基本原則」——「連接查詢」和「設計規範」——「相關注釋」——「字典欄位」有關於字典欄位的詳細介紹,這裡再次說明其命名方式:對於字典欄位,編碼欄位後面跟Code後綴,文本欄位跟Text後綴,比如gender_code、gender_text。

d. 本規範中要求所有表示日期時間的欄位,都要有後綴,如果只精確到天則以Date為後綴,如果要精確到時分秒那就用Time作後綴。在「設計規範」——「欄位設置」——「通用欄位處理」中有關於日期時間類型設置的說明,要求日期時間類型的欄位,儘可能精確到時分秒,即便是像生日(birth_date)這種欄位,一般只存儲到年月日,但在選擇欄位類型時建議還是為datetime而非date。所以這裡的後綴並不是和具體欄位類型對應,而是根據實際業務情況,這個欄位存儲的數據多是精確到年月日還是時分秒,則後綴相應的為Date或Time。

網上有建議說,日期時間不要用Time做後綴,因為Time還有一個很常用的意思,就是次數。比如登錄日誌表中有用戶最後一次登錄時間欄位login_time,不去看錶的內容,很容易將login_time理解成登錄的次數。這裡我們不予考慮,只要內部統一規範,這就不會是個問題。

e. 本規範中建議是否註銷、是否成功等類似的布爾型欄位,名稱前統一加is前綴,比如是否成功(is_success)、是否註銷(is_active)、是否顯示(is_display)等。

f. 關於一些通用欄位的命名方式建議如下,僅作參考:

https://pic1.zhimg.com/v2-ac7295f07397e0e523daa4afff848838_b.png

E.關於約束控制命名

在「設計規範」——「約束控制」中介紹過五種約束類型:唯一性和主鍵約束、外鍵約束、檢查約束、空值約束、默認值約束, 本規範中僅對外鍵約束的命名做要求,因外鍵約束標明著表與表之間的關係。我們建議外鍵約束以fk做前綴,後跟從表名稱和主表名稱:fk_從表名_主表名。這種定義方式,約束名稱很容易超長,比如在Oracle中,約束名稱的長度限制和表名一樣,不能超過30個字元。如果超長,我們建議從後向前自動截取多出部分。前面提到過,CDM轉換成PDM時會自動根據引用關係在從表中添加外鍵欄位,外鍵名稱的命名規則可以自定義。外鍵約束名稱沒必要手動添加,在PD的PDM圖中選擇:Database——Edit current DBMS——General選項卡——右側樹形菜單 ScriptObjectsReferenceConstName ,在裡面可以編輯ConstraintName的命名方式,交由PD自動統一處理,比如可設置為:FK_%.U30:CHILD%_%.U30:PARENT%。此設置在PD 15中起作用,16版本中的設置沒找到。

其它四種約束的命名,本規範中不做要求,竊以為這些約束怎樣命名也不太重要,如果需要統一命名規範, 有些也可藉助PD工具進行統一設置。

F.其它功能塊的命名

前面說過,因為自己所主張的開發模式,以往的項目中很少在資料庫中建存儲過程、觸發器、函數、序列、事件甚至是視圖等,這裡只根據經驗,給出少量建議。

視圖的命名和表的命名有很多相似點,但認為視圖的名稱最好可直接反應出其查詢的主表,或者可明確反應出視圖功能。存儲過程、觸發器、函數、索引的名稱則直接反應其功能為好,其命名方式類似於在編程語言中給某一方法命名。序列只在Oracle中有,一般用來填充主鍵和計數。在早期的資料庫設計中,喜歡用自增主鍵,比如要讓用戶表(USER)的主鍵ID自增,則創建名為SQ_USER_ID的序列和名為TR_SET_USER_ID的觸發器。序列名直接反應出自己要計數的表的列,觸發器名直接反應出自己的功能,這種命名方式或可借鑒。

不過後期項目的資料庫設計,自己不再用自增主鍵,原因在「設計原則」——「基本規範」——「主鍵外鍵」中有描述。如果項目龐大,資料庫設計的模式有變動,要大量使用存儲過程、觸發器、函數、序列等,對於這些部分的命名還是有必要規範化的。

5、梳理總結

「命名規範」牽涉的細節太多,在介紹過程中也一直妄求事無巨細,反而導致有些地方比較散亂,這裡把關鍵部分梳理總結如下:

a. 建議在SQLServer中將排序規則設置為Chinese_PRC_CS_AS,在MySQL資料庫中將Character Set設置為utf8、將Collation設置為utf8_bin,並在資料庫配置文件中設置lower_case_table_names=1,

b. 資料庫、表、欄位等所有名稱的可用字元範圍為:A-Z,a-z, 0-9 和_下劃線,長度要嚴格控制在30個字元以內。

c. 資料庫、表、欄位等所有名稱均使用英文單詞或英文短語或相應縮寫,均使用單數名,禁止使用漢語拼音。

d. Oracle表、欄位等名稱的統一使用大寫,單詞間用_下劃線分隔;SQLServer資料庫、表等名稱採用Pascal命名法,欄位名稱採用Camel命名法;MySQL資料庫、表、欄位等名稱統一使用小寫,單詞間用_下劃線分隔。

e. 表主鍵統一命名為id,主鍵統一使用UUID,類型統一為char(32)。

f. 表(廣義)外鍵建議命名為:主表名_欄位名,類型和主表中欄位類型一樣。如果一個表中有多個外鍵(欄位)同時引用(對應)一張表的同一個欄位,再根據實際情況加前後綴區分

g. 對於字典欄位,編碼欄位後面跟Code後綴,文本欄位跟Text後綴,

h. 表示日期時間的欄位,都要有後綴,如果只精確到天則以Date為後綴,如果要精確到時分秒那就用Time作後綴。

i. 建議是否註銷、是否成功等類似的布爾型欄位,名稱前統一加is前綴,比如是否成功(is_success)、是否註銷(is_active)、是否顯示(is_display)等。

j. 建議外鍵約束以fk做前綴,後跟從表名稱和主表名稱:fk_從表名_主表名。


原文不讓轉載,給你鏈接去看吧
mysql web資料庫的設計歸范-1命名規範

MySQL資料庫命名規範及約定_Mysql_腳本之家


欄位名對應的是類的屬性,類的屬性要用帕斯卡命名法


推薦閱讀:

解釋一下關係資料庫的第一第二第三範式?

TAG:資料庫 | MySQL | 命名規範 | 資料庫設計 |