做爲技術人員,在開發項目中,不可避免的要跟數據庫打交道,一個完整的項目正常狀況下是討論完總體需求,有了大體的框框在腦海中後,是須要設計合理的數據庫的,這時會有其餘的專業的UML建模工具可使用, 可是這種大型的專業化的UML建模工具,僅僅拿來創建數據庫模型顯得大材小用了,而且也過重量級,因此通常都不會輕易使用。多數人會選擇直接在數據庫軟件中直接鼠標操做建表、填充列, 這樣更是不方便, 故而不少人提到了VS中的codefirst方式, 直接在代碼中創建數據庫模型, 這種方式生成數據庫以後,若是回頭維護、查看都不太友好,甚至過了幾個月以後你本身回頭看都有可能不知道是什麼意思。 這樣咱們就須要數據庫說明。javascript
常見的數據庫說明都是word文檔,相似以下:css
這是不少公司或團隊採用的, 可是我以爲這樣仍是不爽,假定你是一個接手人, 你拿着這樣的表格,左邊點開數據庫,右邊打開這個文檔,瞄一眼數據庫再瞄一眼這個表格,左右切換窗口,超級不爽啊。html
另一種更加直觀的,正向思惟的方式:java
這樣看起來是否是直觀多了, 清楚明白的知道這個表的構成,直接在數據庫中打開,不用切換窗口,它是建表腳本,也是一份詳細直觀的數據庫說明文檔, 後續對數據庫進行修改、增長、刪除結構都很直接、直觀。web
因而,我我的就弄了個本身用的方便的可視化的數據庫設計的東西,固然最終是生成上述直觀可讀性高的腳本文件,今天把它寫出來分享下。sql
個人環境是mvc3, 其實這個東西根本用不着MVC, 很簡單,就一個頁面大量的JS操做,提交到後臺代碼生成文件下載回本地。先看打開時:數據庫
默認加載一個空表,填寫相應的名稱之類的,字段、類型、默認值、備註信息等,+號增長一行,若是一行沒有完成會提示:mvc
點擊新建表會增長一個表,整個筐筐內每一個表模型能夠任意拖動位置且高度會自適應。拖拽都是靠JS。整個界面代碼以下:app
1 @{ 2 ViewBag.Title = "主頁"; 3 } 4 <div class="box"> 5 6 7 8 9 <div class="editmenu"> 10 11 <input type="text" id="txtBaseName" value="@ViewBag.baseName"/> 12 13 <input type="text" id="txtBaseDes" value="@ViewBag.baseDes"/> 14 <input id="addTable" type="button" value="新建表"/> 15 <input id="getData" type="button" title="下載完整的TXT格式的數據庫腳本" style="float:right;" value="下載數據"/> 16 17 </div> 18 <div id="main" class="main"> 19 <div class="tbbox"> 20 21 <div class="titletr" title=""> 22 <span class="spleft"> 23 <input value="XXX表" class="tbname" type="text" /> 24 </span> 25 <span class="title"></span> 26 <span class="spright"></span> 27 </div> 28 29 <div class="titletr" title=""> 30 <span class="spleft"> 31 名:<input value="tb_1" class="tbname" type="text" /> 32 </span> 33 <span class="title"></span> 34 <span class="spright">刪除</span> 35 </div> 36 <table class="tablelist"> 37 <tbody> 38 <tr> 39 <td> 40 字段名 41 </td> 42 <td> 43 類型 44 </td> 45 <td> 46 默認值 47 </td> 48 <td> 49 備註 50 </td> 51 <td style="border: 0"> 52 </td> 53 </tr> 54 <tr> 55 <td> 56 <input type="text" /> 57 </td> 58 <td> 59 <div class="sortdiv"> 60 <span class="selspan"> 61 <select class="selsort"> 62 <option value="int">int</option> 63 <option value="varchar(50)">varchar(50)</option> 64 <option value="nvarchar(200)">nvarchar(200)</option> 65 <option value="datetime">datetime</option> 66 <option value="float">float</option> 67 <option value="text">text</option> 68 <option value="ntext">ntext</option> 69 </select> 70 </span> 71 <input value="int" class="sortinput" /> 72 </div> 73 </td> 74 <td> 75 <input class="txtdef" type="text" /> 76 </td> 77 <td> 78 <input type="text" /> 79 </td> 80 <td id="tool" class="jiatr" style="border: 0"> 81 + 82 </td> 83 </tr> 84 </tbody> 85 </table> 86 </div> 87 </div> 88 </div> 89 90 <input id="hdbase" type="hidden" value="@ViewBag.baseId"/> 91 92 <input id="hdtr" type="hidden" value="@ViewBag.Tr"/> 93 <input id="hddiv" type="hidden" value="@ViewBag.div"/> 94 <input id="hdall" type="hidden" value="@ViewBag.AllData"/> 95 96 <script type="text/javascript"> 97 $(document).ready(function () { 98 window.onload = function () { 99 if ($("#hdall").val() != "") { 100 $("#main").html($("#hdall").val()); 101 } 102 ///初始化給div加移動事件 103 $("#main").find("span.title").each(function () { 104 this.onmousedown = MoveBegin; 105 }); 106 ///給+TD事件 107 $("#main").find("td.jiatr").each(function () { 108 $(this).click(TdClick); 109 $(this).attr("title", "新增一行"); 110 }); 111 ///添加DIV按鈕 112 $("#addTable").click(AddTbale); 113 $("#getData").click(GetData); 114 $("#saveData").click(SaveData); 115 ///給select綁定事件 116 $("#main").find("div.tbbox").each(function () { 117 SortList(this); 118 $(this).find("span.spright").click(DelDiv); 119 }); 120 121 CheckMainHeight(); 122 123 } 124 ///返回txt文件 125 function SaveTxt(arr) { 126 var loogParam = arr; 127 var nwin = window.open('/home/DataText?t=' + Math.random(), 'newwindow', 'height=5, width=5, top=400,left=500, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no'); 128 document.body.insertAdjacentHTML("beforeEnd", "<form name='form1' action='/home/DataText' target='newpage' method='post'><input type='hidden' name='param'></form>"); 129 document.form1.param.value = loogParam; 130 document.form1.submit(); 131 $("form").remove(); 132 nwin.close(); 133 } 134 135 ///txt文件空格佔位 136 function NullSpace(defnum, str) { 137 var s = "\040"; 138 var r = ""; 139 var l = str.length; 140 var num = defnum - l; 141 for (var i = 0; i < num; i++) { 142 r += s; 143 } 144 return r; 145 } 146 ///"-"佔位符 147 function NullH(defnum, str) { 148 var s = "-"; 149 var r = ""; 150 var l = str.length; 151 var num = defnum - l; 152 for (var i = 0; i < num; i++) { 153 r += s; 154 } 155 return r; 156 } 157 158 159 ///下載腳本爲txt文件 160 function GetData() { 161 var tbName = ""; 162 var tr = 0; 163 var sav = true; 164 var br = "\r\n"; 165 var strSql = "use " + $("#txtBaseName").val() + br; 166 $("#main").find("div.tbbox").each(function () { 167 tbName = $($(this).find(".tbname")[1]).val(); 168 var desName = $($(this).find(".tbname")[0]).val(); 169 var sqlExists = "if exists ( select * from sysobjects where name = '" + tbName + "' and xtype='U') " + br + "" 170 + "drop table " + tbName + ""; 171 strSql += sqlExists + br; 172 strSql += "create table " + tbName + NullH(67, tbName) + desName + br + "(" + br; 173 $(this).find("tr").each(function (index, element) { 174 if (index > 0) { 175 var tdlist = $(this).find("td"); 176 var key = $(tdlist[0]).find("input").val(); 177 if ($.trim(key) != "") { 178 if (key.length >= 17) { 179 alert(key + "超出了15個字符的限制"); 180 //alert(strSql); 181 sav = false; 182 return; 183 } 184 key += NullSpace(17, key); 185 var col = $(tdlist[1]).find("input").val(); 186 col += NullSpace(17, col); 187 if (index == 1) 188 col = "int" + NullSpace(17, "int"); 189 var def = $(tdlist[2]).find("input").val() == "" ? "default ''" : "default " + $(tdlist[2]).find("input").val(); 190 def += NullSpace(32, def); 191 if (index == 1) 192 def = "primary key identity(1,1)" + NullSpace(32, "primary key identity(1,1)"); 193 var des = "--" + $(tdlist[3]).find("input").val(); 194 if (index == 1) 195 des = "--主鍵-" + $(tdlist[3]).find("input").val(); 196 strSql += "\040\040" + key + col + def + "NOT NULL , " + des + br; 197 198 tr++; 199 } 200 } 201 }); 202 strSql += ");" + br + br + br; 203 }); 204 if (sav && tr > 0) { 205 $("#saveData").click(); 206 SaveTxt(strSql); 207 } 208 } 209 210 211 ///給數據類型列加事件 212 function SortList(obj) { 213 $(obj).find("div.sortdiv").each(function () { 214 215 216 $(this).find("select:first").change(ChangeVal).change(DefaultTxt); 217 $(this).find("input:first").focus(ShowSel); 218 219 $(this.parentNode).mouseenter(ShowSel).mouseleave(HideSel); 220 221 $(this.parentNode.parentNode).find(".txtdef").blur(DefaultTxt); 222 223 }); 224 225 } 226 227 ///刪除div 228 function DelDiv() { 229 $(this.parentNode.parentNode).remove(); 230 } 231 232 233 234 ///改變數據類型 235 function ChangeVal(obj) { 236 $(this.parentNode.parentNode).find(".sortinput").val($(this.parentNode).find(".selsort").val()); 237 238 239 } 240 ///默認值 241 function DefaultTxt(obj) { 242 var txt = $(this.parentNode.parentNode).find(".txtdef:first")[0]; 243 if (obj.type == "change") { 244 txt = $(this.parentNode.parentNode.parentNode.parentNode).find(".txtdef:first")[0]; 245 } 246 var val = $(txt).val().replace("'", "").replace("'", ""); 247 $(txt).val(val); 248 if ($.trim($(txt).val()) != "" && $.trim($(txt).val().toLowerCase()) != "getdate()" && $.trim($(txt.parentNode.parentNode).find(".sortinput").val()) != "int" && $.trim($(txt.parentNode.parentNode).find(".sortinput").val()) != "float") { 249 250 $(txt).val("'" + val + "'"); 251 } 252 } 253 ///數據類型下拉顯示 254 function ShowSel(obj) { 255 $(this.parentNode).find(".selspan").show(); 256 $(this.parentNode).find(".sortinput").width("90px"); 257 $(this.parentNode).find(".sortinput").css("position", "absolute"); 258 } 259 ///數據類型下拉隱藏 260 function HideSel(obj) { 261 var td = this; 262 var o = obj.relatedTarget || obj.toElement; 263 if (!o) { 264 return; 265 } 266 $(td).find(".selspan").hide(); 267 $(td).find(".sortinput").width("118px"); 268 $(td).find(".sortinput").css("position", ""); 269 } 270 271 272 273 ///添加DIV 274 function AddTbale() { 275 var child = document.createElement("div"); 276 child.className = "tbbox"; 277 var name = Math.random().toString().substr(2, 3); 278 var div = $("#hddiv").val().replace("tb_Name", "tb_" + name); 279 $(child).html(div); 280 $(child).find("span.title").each(function () { 281 this.onmousedown = MoveBegin; 282 }); 283 284 285 286 287 $(child).find("span.spright").click(DelDiv); 288 $(child).find("td.jiatr").each(function () { 289 $(this).click(TdClick); 290 $(this).attr("title", "新增一行"); 291 }); 292 SortList(child); 293 $("#main").append(child); 294 CheckMainHeight(); 295 } 296 297 ///TD增長一行點擊 298 function TdClick(obj) { 299 var tooltipem = $(this.parentNode).find("td:first").find("input:first"); 300 if ($.trim(tooltipem.val()) == "") { 301 $(tooltipem).tooltip({ 302 "title": "這裏還沒填寫呢~!", 303 "trigger": "manual", 304 "placement": "right", 305 "delay": 800 306 }); 307 $(tooltipem).tooltip("show"); 308 309 $(tooltipem).focus(); 310 setTimeout(function () { $(tooltipem).tooltip("hide"); }, 1800) 311 312 return false; 313 } 314 $(tooltipem).tooltip("destroy"); 315 var tr = $("#hdtr").val(); 316 var child = document.createElement("tr"); 317 $(child).html(tr); 318 $(this.parentNode.parentNode).append(child); 319 SortList(child); 320 $(child).find("td.jiatr").click(TdClick); 321 322 323 $(this).removeClass(); 324 $(this).unbind(); 325 $(this).html(""); 326 $(this).attr("title", ""); 327 328 CheckMainHeight(); 329 $($($(this.parentNode.parentNode).find("tr:first").next("tr"))).find("td:last").addClass("prmkey").attr("title", "第一行默認爲主鍵&自增加"); 330 } 331 ///校驗div#main高度 332 function CheckMainHeight() { 333 $("#main").find("div").each(function () { 334 if (this.offsetTop + $(this).height() > $("#main").height()) 335 $("#main").height(this.offsetTop + $(this).height() + 10); 336 }); 337 } 338 339 ///移動 340 function MoveBegin(obj) { 341 var e = obj || window.event, 342 x1 = e.clientX; 343 y1 = e.clientY; 344 var setOn = this.parentNode.parentNode; 345 var defLeft = setOn.offsetLeft; 346 var defTop = setOn.offsetTop; 347 348 document.onmousemove = function (event) { 349 var e = event || window.event; 350 // 351 x2 = e.clientX; 352 y2 = e.clientY; 353 // 354 x = x2 - x1; 355 y = y2 - y1; 356 var setLeft = defLeft + x; 357 var setTop = defTop + y; 358 setOn.style.position = "absolute"; 359 //setOn.style.filter = 'alpha(opacity=80)'; 360 //setOn.style.opacity = "0.8"; 361 if (setLeft <= 0) { 362 setLeft = 0; 363 } 364 if (setTop <= 0) { 365 setTop = 0; 366 } 367 if (setLeft >= $("#main").width() - $(setOn).width() - 9) { 368 setLeft = $("#main").width() - $(setOn).width() - 14; 369 } 370 if (setTop > $("#main").height() - $(setOn).height() + 10) { 371 372 $("#main").height(setTop + $(setOn).height() + 100); 373 374 setTop = $("#main").height() - $(setOn).height(); 375 } 376 setOn.style.left = setLeft + 'px'; 377 setOn.style.top = setTop + 'px'; 378 //$("#showText").text("Top:" + setOn.style.top + "; Left:" + setOn.style.left + "; OFl:" + ""); 379 } 380 document.onmouseup = function () { 381 this.onmousemove = null; 382 } 383 } 384 385 }); 386 </script>
裏面有JS拖拽代碼, 都很簡單, 上面這些是我2年前作的東西,不少命名之類的都不規範,你們關注方法就好。dom
後臺代碼:
1 public ActionResult Index() 2 { 3 StringBuilder sb = new StringBuilder(); 4 5 sb.Append("<td>"); 6 sb.Append("<input type=\"text\" />"); 7 sb.Append("</td>"); 8 sb.Append("<td>"); 9 sb.Append("<div class=\"sortdiv\">"); 10 sb.Append("<span class=\"selspan\">"); 11 sb.Append("<select class=\"selsort\">"); 12 sb.Append("<option value=\"int\">int</option>"); 13 sb.Append("<option value=\"varchar(50)\">varchar(50)</option>"); 14 sb.Append(" <option value=\"nvarchar(200)\">nvarchar(200)</option>"); 15 sb.Append("<option value=\"datetime\">datetime</option>"); 16 sb.Append("<option value=\"float\">float</option>"); 17 sb.Append("<option value=\"text\">text</option>"); 18 sb.Append("<option value=\"ntext\">ntext</option>"); 19 sb.Append("</select>"); 20 sb.Append("</span>"); 21 sb.Append("<input value=\"int\" class=\"sortinput\" />"); 22 sb.Append("</div>"); 23 sb.Append("</td>"); 24 sb.Append("<td>"); 25 sb.Append("<input class=\"txtdef\" type=\"text\" />"); 26 sb.Append("</td>"); 27 sb.Append("<td>"); 28 sb.Append("<input type=\"text\" />"); 29 sb.Append("</td>"); 30 sb.Append("<td id=\"tool\" class=\"jiatr\" title=\"新增一行\" style=\"border: 0\">"); 31 sb.Append("+"); 32 sb.Append("</td>"); 33 ViewBag.Tr = sb.ToString(); 34 35 StringBuilder sbdiv = new StringBuilder(); 36 sbdiv.Append("<div class='titletr' title=''>"); 37 sbdiv.Append("<span class='spleft'>"); 38 sbdiv.Append("<input value='XXX表' class='tbname' type='text' />"); 39 sbdiv.Append("</span>"); 40 sbdiv.Append("<span class='title'></span>"); 41 sbdiv.Append("<span class='spright'></span>"); 42 sbdiv.Append("</div>"); 43 sbdiv.Append("<div class='titletr' title=''>"); 44 sbdiv.Append("<span class='spleft'>"); 45 sbdiv.Append("名:<input value='tb_Name' class='tbname' type='text' />"); 46 sbdiv.Append("</span>"); 47 sbdiv.Append("<span class='title'></span>"); 48 sbdiv.Append("<span class='spright'>刪除</span>"); 49 sbdiv.Append("</div>"); 50 sbdiv.Append("<table class='tablelist'>"); 51 sbdiv.Append("<tbody>"); 52 sbdiv.Append("<tr>"); 53 sbdiv.Append("<td>"); 54 sbdiv.Append("字段名"); 55 sbdiv.Append("</td>"); 56 sbdiv.Append("<td>"); 57 sbdiv.Append("類型"); 58 sbdiv.Append("</td>"); 59 sbdiv.Append("<td>"); 60 sbdiv.Append("默認值"); 61 sbdiv.Append("</td>"); 62 sbdiv.Append("<td>"); 63 sbdiv.Append(" 備註"); 64 sbdiv.Append("</td>"); 65 sbdiv.Append("<td style='border: 0'>"); 66 sbdiv.Append("</td>"); 67 sbdiv.Append("</tr>"); 68 sbdiv.Append("<tr>"); 69 sbdiv.Append("<td>"); 70 sbdiv.Append("<input type='text' />"); 71 sbdiv.Append("</td>"); 72 sbdiv.Append("<td>"); 73 sbdiv.Append("<div class='sortdiv'>"); 74 sbdiv.Append("<span class='selspan'>"); 75 sbdiv.Append("<select class='selsort'>"); 76 sbdiv.Append("<option value='int'>int</option>"); 77 sbdiv.Append("<option value='varchar(50)'>varchar(50)</option>"); 78 sbdiv.Append("<option value='nvarchar(200)'>nvarchar(200)</option>"); 79 sbdiv.Append("<option value='datetime'>datetime</option>"); 80 sbdiv.Append("<option value='float'>float</option>"); 81 sbdiv.Append("<option value='text'>text</option>"); 82 sbdiv.Append("<option value='ntext'>ntext</option>"); 83 sbdiv.Append("</select>"); 84 sbdiv.Append("</span>"); 85 sbdiv.Append("<input value='int' class='sortinput' />"); 86 sbdiv.Append("</div>"); 87 sbdiv.Append("</td>"); 88 sbdiv.Append("<td>"); 89 sbdiv.Append("<input class='txtdef' type='text' />"); 90 sbdiv.Append("</td>"); 91 sbdiv.Append("<td>"); 92 sbdiv.Append("<input type='text' />"); 93 sbdiv.Append("</td>"); 94 sbdiv.Append("<td id='tool' class='jiatr' style='border: 0'>"); 95 sbdiv.Append(" +"); 96 sbdiv.Append("</td>"); 97 sbdiv.Append("</tr>"); 98 sbdiv.Append("</tbody>"); 99 sbdiv.Append("</table>"); 100 ViewBag.div = sbdiv.ToString(); 101 ViewBag.AllData = ""; 102 ViewBag.baseId = ""; 103 ViewBag.baseName = "basename"; 104 ViewBag.baseDes = "備註說明"; 105 106 return View(); 107 108 } 109 //響應下載腳本請求,返回txt文件 110 public void DataText() 111 { 112 if (Request["param"] == null) 113 return; 114 string t = Request["param"]; 115 if (t == "") 116 return; 117 string tbName = "數據庫-" + System.DateTime.Now.ToString("yyMMdd-HHmmss")+".sql"; 118 Response.AppendHeader("Content-Disposition", "attachment;filename=" + tbName); 119 Response.ContentEncoding = System.Text.Encoding.Default; 120 Response.ContentType = "text/plain"; 121 Response.Write(t); 122 }
在線暫時測試地址:http://websql.puworld.com