???問(wèn)題:
??????SQL查詢中經(jīng)常需要借助於表的 primary key 來(lái)實(shí)現(xiàn)記錄的唯一性標(biāo)識(shí),但是有的場(chǎng)合中卻不方便對(duì)主鍵進(jìn)行直接處理,例如我遇到的這種情況:
??????表A具有PK列,我現(xiàn)在需要在頁(yè)面上Show出以 CheckBox 表示的記錄條,類似於郵件列表的選取。
??????通常的做法會(huì)是利用表A的PK列來(lái)形成 頁(yè)面元素 的ID,這樣在FORM的Submit中就可以拿到選取的記錄PK值,可以很方便的組織SQL來(lái)完成整個(gè)篩選邏輯。
???????現(xiàn)在的問(wèn)題是出在這個(gè)表A的PK列上,通常表的PK列會(huì)利用 Int 類型來(lái)建立,這樣建立唯一索引的代價(jià)會(huì)比較小,用Char來(lái)建立PK時(shí)的情況也是很多,但是也會(huì)保證該列的規(guī)則性。可是表A的PK列是建立在一個(gè)具有實(shí)際含義的Char列上,該列的內(nèi)容會(huì)是用戶手工輸入的結(jié)果,可想而知如果用它來(lái)構(gòu)造頁(yè)面元素的ID會(huì)發(fā)生什麼情況:
??????? 1.如果該列寬很大的話,當(dāng)然就會(huì)出錯(cuò);
??????? 2.由於該列內(nèi)容不會(huì)是非常“正規(guī)”的內(nèi)容,很有可能包含一些特殊字符,這樣一定會(huì)使瀏覽器在解析頁(yè)面時(shí)產(chǎn)生歧義。
???解決方法:
???????問(wèn)題2的情況可以通過(guò)對(duì)表的PK列進(jìn)行字符替換等手段來(lái)排除掉特殊字符,但是問(wèn)題1的長(zhǎng)度過(guò)長(zhǎng)依舊不能夠解決。
???????我想到的解決該問(wèn)題的方法是:
??????1.對(duì)PK列進(jìn)行字符替換處理這樣可以被保存在 textarea 這樣的元素裡;
??????2.而需要提交的元素ID則由我以SQL構(gòu)造的 Identity 列來(lái)構(gòu)造;
??????3.生成頁(yè)面的時(shí)候只需要建立起提交元素與 textarea 的關(guān)聯(lián)即可,最終提交的還是PK的值。
??????可能有人會(huì)對(duì)解決方法3提出疑問(wèn),既然可以構(gòu)造 Identity 列,為啥不直接用它來(lái)實(shí)現(xiàn)提交呢?
??????看過(guò)實(shí)現(xiàn)就知道了:
????????????MyIDCol = (
???????????????? Select ? Count ( * )? From ?A?subA? Where ?subA.pkCol = A.pkCol? And ?A.pkCol? < ?subA.pkCol
????????????),
????????????pkCol,
????????????col1,
????????????col2
???????? From
????????????A
??????這裡可以看 Identity 列(MyIDCol) 是構(gòu)建在唯一查詢的排序結(jié)果集上的,因此它在工作時(shí)總能夠保證唯一的區(qū)分每一行記錄。
??????但是需要注意的一點(diǎn)就是這條語(yǔ)句形成的 Identity 是關(guān)聯(lián)到某一時(shí)刻的,換句話說(shuō),如果在用戶對(duì)記錄進(jìn)行過(guò) Insert/Delete 操作之後,這個(gè)Identity的值與做DML之前的記錄是關(guān)聯(lián)不上的,因此需要在Select時(shí)帶出PK列的值,在提交時(shí)使用PK值才能保證數(shù)據(jù)的正確性。
??????當(dāng)然,改變DB的設(shè)計(jì)也是可行的,只不過(guò)前提是必須在DB的設(shè)計(jì)階段。