作为技术人员,在开发项目中,不可避免的要跟数据库打交道,一个完整的项目正常情况下是讨论完整体需求,有了大致的框框在脑海中后,是需要设计合理的数据库的,这时会有其他的专业的UML建模工具可以使用, 但是这种大型的专业化的UML建模工具,仅仅拿来建立数据库模型显得大材小用了,并且也太重量级,所以一般都不会轻易使用。多数人会选择直接在数据库软件中直接鼠标操作建表、填充列, 这样更是不方便,  故而很多人提到了VS中的codefirst方式,  直接在代码中建立数据库模型,  这种方式生成数据库之后,如果回头维护、查看都不太友好,甚至过了几个月之后你自己回头看都有可能不知道是什么意思。  这样我们就需要数据库说明。

常见的数据库说明都是word文档,类似如下:

这是很多公司或团队采用的, 但是我觉得这样还是不爽,假定你是一个接手人, 你拿着这样的表格,左边点开数据库,右边打开这个文档,瞄一眼数据库再瞄一眼这个表格,左右切换窗口,超级不爽啊。

另外一种更加直观的,正向思维的方式:

这样看起来是不是直观多了,  清楚明白的知道这个表的构成,直接在数据库中打开,不用切换窗口,它是建表脚本,也是一份详细直观的数据库说明文档, 后续对数据库进行修改、增加、删除结构都很直接、直观。

于是,我个人就弄了个自己用的方便的可视化的数据库设计的东西,当然最终是生成上述直观可读性高的脚本文件,今天把它写出来分享下。

我的环境是mvc3,  其实这个东西根本用不着MVC,  很简单,就一个页面大量的JS操作,提交到后台代码生成文件下载回本地。先看打开时:

默认加载一个空表,填写相应的名称之类的,字段、类型、默认值、备注信息等,+号增加一行,如果一行没有完成会提示:

点击新建表会增加一个表,整个筐筐内每个表模型可以任意拖动位置且高度会自适应。拖拽都是靠JS。整个界面代码如下:

 @{
ViewBag.Title = "主页";
}
<div class="box"> <div class="editmenu"> <input type="text" id="txtBaseName" value="@ViewBag.baseName"/> <input type="text" id="txtBaseDes" value="@ViewBag.baseDes"/>
<input id="addTable" type="button" value="新建表"/>
<input id="getData" type="button" title="下载完整的TXT格式的数据库脚本" style="float:right;" value="下载数据"/> </div>
<div id="main" class="main">
<div class="tbbox"> <div class="titletr" title="">
<span class="spleft">
<input value="XXX表" class="tbname" type="text" />
</span>
<span class="title"></span>
<span class="spright"></span>
</div> <div class="titletr" title="">
<span class="spleft">
名:<input value="tb_1" class="tbname" type="text" />
</span>
<span class="title"></span>
<span class="spright">删除</span>
</div>
<table class="tablelist">
<tbody>
<tr>
<td>
字段名
</td>
<td>
类型
</td>
<td>
默认值
</td>
<td>
备注
</td>
<td style="border: 0">
</td>
</tr>
<tr>
<td>
<input type="text" />
</td>
<td>
<div class="sortdiv">
<span class="selspan">
<select class="selsort">
<option value="int">int</option>
<option value="varchar(50)">varchar(50)</option>
<option value="nvarchar(200)">nvarchar(200)</option>
<option value="datetime">datetime</option>
<option value="float">float</option>
<option value="text">text</option>
<option value="ntext">ntext</option>
</select>
</span>
<input value="int" class="sortinput" />
</div>
</td>
<td>
<input class="txtdef" type="text" />
</td>
<td>
<input type="text" />
</td>
<td id="tool" class="jiatr" style="border: 0">
+
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div> <input id="hdbase" type="hidden" value="@ViewBag.baseId"/> <input id="hdtr" type="hidden" value="@ViewBag.Tr"/>
<input id="hddiv" type="hidden" value="@ViewBag.div"/>
<input id="hdall" type="hidden" value="@ViewBag.AllData"/> <script type="text/javascript">
$(document).ready(function () {
window.onload = function () {
if ($("#hdall").val() != "") {
$("#main").html($("#hdall").val());
}
///初始化给div加移动事件
$("#main").find("span.title").each(function () {
this.onmousedown = MoveBegin;
});
///给+TD事件
$("#main").find("td.jiatr").each(function () {
$(this).click(TdClick);
$(this).attr("title", "新增一行");
});
///添加DIV按钮
$("#addTable").click(AddTbale);
$("#getData").click(GetData);
$("#saveData").click(SaveData);
///给select绑定事件
$("#main").find("div.tbbox").each(function () {
SortList(this);
$(this).find("span.spright").click(DelDiv);
}); CheckMainHeight(); }
///返回txt文件
function SaveTxt(arr) {
var loogParam = arr;
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');
document.body.insertAdjacentHTML("beforeEnd", "<form name='form1' action='/home/DataText' target='newpage' method='post'><input type='hidden' name='param'></form>");
document.form1.param.value = loogParam;
document.form1.submit();
$("form").remove();
nwin.close();
} ///txt文件空格占位
function NullSpace(defnum, str) {
var s = "\040";
var r = "";
var l = str.length;
var num = defnum - l;
for (var i = 0; i < num; i++) {
r += s;
}
return r;
}
///"-"占位符
function NullH(defnum, str) {
var s = "-";
var r = "";
var l = str.length;
var num = defnum - l;
for (var i = 0; i < num; i++) {
r += s;
}
return r;
} ///下载脚本为txt文件
function GetData() {
var tbName = "";
var tr = 0;
var sav = true;
var br = "\r\n";
var strSql = "use " + $("#txtBaseName").val() + br;
$("#main").find("div.tbbox").each(function () {
tbName = $($(this).find(".tbname")[1]).val();
var desName = $($(this).find(".tbname")[0]).val();
var sqlExists = "if exists ( select * from sysobjects where name = '" + tbName + "' and xtype='U') " + br + ""
+ "drop table " + tbName + "";
strSql += sqlExists + br;
strSql += "create table " + tbName + NullH(67, tbName) + desName + br + "(" + br;
$(this).find("tr").each(function (index, element) {
if (index > 0) {
var tdlist = $(this).find("td");
var key = $(tdlist[0]).find("input").val();
if ($.trim(key) != "") {
if (key.length >= 17) {
alert(key + "超出了15个字符的限制");
//alert(strSql);
sav = false;
return;
}
key += NullSpace(17, key);
var col = $(tdlist[1]).find("input").val();
col += NullSpace(17, col);
if (index == 1)
col = "int" + NullSpace(17, "int");
var def = $(tdlist[2]).find("input").val() == "" ? "default ''" : "default " + $(tdlist[2]).find("input").val();
def += NullSpace(32, def);
if (index == 1)
def = "primary key identity(1,1)" + NullSpace(32, "primary key identity(1,1)");
var des = "--" + $(tdlist[3]).find("input").val();
if (index == 1)
des = "--主键-" + $(tdlist[3]).find("input").val();
strSql += "\040\040" + key + col + def + "NOT NULL , " + des + br; tr++;
}
}
});
strSql += ");" + br + br + br;
});
if (sav && tr > 0) {
$("#saveData").click();
SaveTxt(strSql);
}
} ///给数据类型列加事件
function SortList(obj) {
$(obj).find("div.sortdiv").each(function () { $(this).find("select:first").change(ChangeVal).change(DefaultTxt);
$(this).find("input:first").focus(ShowSel); $(this.parentNode).mouseenter(ShowSel).mouseleave(HideSel); $(this.parentNode.parentNode).find(".txtdef").blur(DefaultTxt); }); } ///删除div
function DelDiv() {
$(this.parentNode.parentNode).remove();
} ///改变数据类型
function ChangeVal(obj) {
$(this.parentNode.parentNode).find(".sortinput").val($(this.parentNode).find(".selsort").val()); }
///默认值
function DefaultTxt(obj) {
var txt = $(this.parentNode.parentNode).find(".txtdef:first")[0];
if (obj.type == "change") {
txt = $(this.parentNode.parentNode.parentNode.parentNode).find(".txtdef:first")[0];
}
var val = $(txt).val().replace("'", "").replace("'", "");
$(txt).val(val);
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") { $(txt).val("'" + val + "'");
}
}
///数据类型下拉显示
function ShowSel(obj) {
$(this.parentNode).find(".selspan").show();
$(this.parentNode).find(".sortinput").width("90px");
$(this.parentNode).find(".sortinput").css("position", "absolute");
}
///数据类型下拉隐藏
function HideSel(obj) {
var td = this;
var o = obj.relatedTarget || obj.toElement;
if (!o) {
return;
}
$(td).find(".selspan").hide();
$(td).find(".sortinput").width("118px");
$(td).find(".sortinput").css("position", "");
} ///添加DIV
function AddTbale() {
var child = document.createElement("div");
child.className = "tbbox";
var name = Math.random().toString().substr(2, 3);
var div = $("#hddiv").val().replace("tb_Name", "tb_" + name);
$(child).html(div);
$(child).find("span.title").each(function () {
this.onmousedown = MoveBegin;
}); $(child).find("span.spright").click(DelDiv);
$(child).find("td.jiatr").each(function () {
$(this).click(TdClick);
$(this).attr("title", "新增一行");
});
SortList(child);
$("#main").append(child);
CheckMainHeight();
} ///TD增加一行点击
function TdClick(obj) {
var tooltipem = $(this.parentNode).find("td:first").find("input:first");
if ($.trim(tooltipem.val()) == "") {
$(tooltipem).tooltip({
"title": "这里还没填写呢~!",
"trigger": "manual",
"placement": "right",
"delay": 800
});
$(tooltipem).tooltip("show"); $(tooltipem).focus();
setTimeout(function () { $(tooltipem).tooltip("hide"); }, 1800) return false;
}
$(tooltipem).tooltip("destroy");
var tr = $("#hdtr").val();
var child = document.createElement("tr");
$(child).html(tr);
$(this.parentNode.parentNode).append(child);
SortList(child);
$(child).find("td.jiatr").click(TdClick); $(this).removeClass();
$(this).unbind();
$(this).html("");
$(this).attr("title", ""); CheckMainHeight();
$($($(this.parentNode.parentNode).find("tr:first").next("tr"))).find("td:last").addClass("prmkey").attr("title", "第一行默认为主键&自增长");
}
///校验div#main高度
function CheckMainHeight() {
$("#main").find("div").each(function () {
if (this.offsetTop + $(this).height() > $("#main").height())
$("#main").height(this.offsetTop + $(this).height() + 10);
});
} ///移动
function MoveBegin(obj) {
var e = obj || window.event,
x1 = e.clientX;
y1 = e.clientY;
var setOn = this.parentNode.parentNode;
var defLeft = setOn.offsetLeft;
var defTop = setOn.offsetTop; document.onmousemove = function (event) {
var e = event || window.event;
//
x2 = e.clientX;
y2 = e.clientY;
//
x = x2 - x1;
y = y2 - y1;
var setLeft = defLeft + x;
var setTop = defTop + y;
setOn.style.position = "absolute";
//setOn.style.filter = 'alpha(opacity=80)';
//setOn.style.opacity = "0.8";
if (setLeft <= 0) {
setLeft = 0;
}
if (setTop <= 0) {
setTop = 0;
}
if (setLeft >= $("#main").width() - $(setOn).width() - 9) {
setLeft = $("#main").width() - $(setOn).width() - 14;
}
if (setTop > $("#main").height() - $(setOn).height() + 10) { $("#main").height(setTop + $(setOn).height() + 100); setTop = $("#main").height() - $(setOn).height();
}
setOn.style.left = setLeft + 'px';
setOn.style.top = setTop + 'px';
//$("#showText").text("Top:" + setOn.style.top + "; Left:" + setOn.style.left + "; OFl:" + "");
}
document.onmouseup = function () {
this.onmousemove = null;
}
} });
</script>

里面有JS拖拽代码,  都很简单,  上面这些是我2年前做的东西,很多命名之类的都不规范,大家关注方法就好。

后台代码:

    public ActionResult Index()
{
StringBuilder sb = new StringBuilder(); sb.Append("<td>");
sb.Append("<input type=\"text\" />");
sb.Append("</td>");
sb.Append("<td>");
sb.Append("<div class=\"sortdiv\">");
sb.Append("<span class=\"selspan\">");
sb.Append("<select class=\"selsort\">");
sb.Append("<option value=\"int\">int</option>");
sb.Append("<option value=\"varchar(50)\">varchar(50)</option>");
sb.Append(" <option value=\"nvarchar(200)\">nvarchar(200)</option>");
sb.Append("<option value=\"datetime\">datetime</option>");
sb.Append("<option value=\"float\">float</option>");
sb.Append("<option value=\"text\">text</option>");
sb.Append("<option value=\"ntext\">ntext</option>");
sb.Append("</select>");
sb.Append("</span>");
sb.Append("<input value=\"int\" class=\"sortinput\" />");
sb.Append("</div>");
sb.Append("</td>");
sb.Append("<td>");
sb.Append("<input class=\"txtdef\" type=\"text\" />");
sb.Append("</td>");
sb.Append("<td>");
sb.Append("<input type=\"text\" />");
sb.Append("</td>");
sb.Append("<td id=\"tool\" class=\"jiatr\" title=\"新增一行\" style=\"border: 0\">");
sb.Append("+");
sb.Append("</td>");
ViewBag.Tr = sb.ToString(); StringBuilder sbdiv = new StringBuilder();
sbdiv.Append("<div class='titletr' title=''>");
sbdiv.Append("<span class='spleft'>");
sbdiv.Append("<input value='XXX表' class='tbname' type='text' />");
sbdiv.Append("</span>");
sbdiv.Append("<span class='title'></span>");
sbdiv.Append("<span class='spright'></span>");
sbdiv.Append("</div>");
sbdiv.Append("<div class='titletr' title=''>");
sbdiv.Append("<span class='spleft'>");
sbdiv.Append("名:<input value='tb_Name' class='tbname' type='text' />");
sbdiv.Append("</span>");
sbdiv.Append("<span class='title'></span>");
sbdiv.Append("<span class='spright'>删除</span>");
sbdiv.Append("</div>");
sbdiv.Append("<table class='tablelist'>");
sbdiv.Append("<tbody>");
sbdiv.Append("<tr>");
sbdiv.Append("<td>");
sbdiv.Append("字段名");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append("类型");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append("默认值");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append(" 备注");
sbdiv.Append("</td>");
sbdiv.Append("<td style='border: 0'>");
sbdiv.Append("</td>");
sbdiv.Append("</tr>");
sbdiv.Append("<tr>");
sbdiv.Append("<td>");
sbdiv.Append("<input type='text' />");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append("<div class='sortdiv'>");
sbdiv.Append("<span class='selspan'>");
sbdiv.Append("<select class='selsort'>");
sbdiv.Append("<option value='int'>int</option>");
sbdiv.Append("<option value='varchar(50)'>varchar(50)</option>");
sbdiv.Append("<option value='nvarchar(200)'>nvarchar(200)</option>");
sbdiv.Append("<option value='datetime'>datetime</option>");
sbdiv.Append("<option value='float'>float</option>");
sbdiv.Append("<option value='text'>text</option>");
sbdiv.Append("<option value='ntext'>ntext</option>");
sbdiv.Append("</select>");
sbdiv.Append("</span>");
sbdiv.Append("<input value='int' class='sortinput' />");
sbdiv.Append("</div>");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append("<input class='txtdef' type='text' />");
sbdiv.Append("</td>");
sbdiv.Append("<td>");
sbdiv.Append("<input type='text' />");
sbdiv.Append("</td>");
sbdiv.Append("<td id='tool' class='jiatr' style='border: 0'>");
sbdiv.Append(" +");
sbdiv.Append("</td>");
sbdiv.Append("</tr>");
sbdiv.Append("</tbody>");
sbdiv.Append("</table>");
ViewBag.div = sbdiv.ToString();
ViewBag.AllData = "";
ViewBag.baseId = "";
ViewBag.baseName = "basename";
ViewBag.baseDes = "备注说明"; return View(); }
//响应下载脚本请求,返回txt文件
public void DataText()
{
if (Request["param"] == null)
return;
string t = Request["param"];
if (t == "")
return;
string tbName = "数据库-" + System.DateTime.Now.ToString("yyMMdd-HHmmss")+".sql";
Response.AppendHeader("Content-Disposition", "attachment;filename=" + tbName);
Response.ContentEncoding = System.Text.Encoding.Default;
Response.ContentType = "text/plain";
Response.Write(t);
}

在线暂时测试地址:http://websql.puworld.com

工欲善其事必先利其器---SQL在线可视化模型设计,(还可学习拖拽知识)的更多相关文章

  1. h5页面ios,双击向上滑动,拖拽到底部还能继续拖拽(露出黑色背景)

    h5页面ios,双击向上滑动,拖拽到底部还能继续拖拽 标签: 手机 2016-02-02 18:09 696人阅读 评论(0) 收藏 举报   在ios下,双击屏幕某些地方,滚动条会自动向上走一段. ...

  2. 古语云:工欲善其事必先利其器 --> 最新、最全的 IntelliJ IDEA(2018.3.3) 的介绍、安装、破解、配置与使用

    原文:古语云:工欲善其事必先利其器 --> 最新.最全的 IntelliJ IDEA(2018.3.3) 的介绍.安装.破解.配置与使用 一.IntelliJ IDEA 介绍 -> Ecl ...

  3. TIZ_c 第0周总结(2019/10/15-2019/10/22)工欲善其事必先利其器

    TIZ_c 第0周总结(2019/10/15-2019/10/22)工欲善其事必先利其器 任务清单 给自己取一个酷酷的id,并选择1-2个喜欢的方向.(只是初步选择,后期可更改) 改下群名片.例如yo ...

  4. 转:【工欲善其事必先利其器】—Entity Framework实例详解

    开始本篇文章之前,先说一下Entity Framework 6 Alpha1在NuGet中已可用,原文链接http://blogs.msdn.com/b/adonet/archive/2012/10/ ...

  5. 单片机开发——02工欲善其事必先利其器(Proteus软件安装破解)

    在单片机开发工程中,博主经常通过模拟软件Proteus进行模拟仿真,将编译生成的"HEX"文件下载在单片机芯片中,然后进行后期的debug工作,当模拟仿真完成之后,进行硬件测试部分 ...

  6. 单片机开发——01工欲善其事必先利其器(Keil软件安装破解)

        本文是博主<单片机开发>博客第一篇文章,主要讲述51单片机编程软件Keil uVision4的安装及破解过程. 1. Keil uVision4安装包文件      PATH:链接 ...

  7. yaml语言在线可视化翻译

    yaml语言在线可视化翻译 https://editor.swagger.io/

  8. [sql Server]除非另外还指定了TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效

    今天遇到一个奇怪的问题,项目突然要从mysql切换到sql server数据库,包含order by 子句的嵌套子查询报错. 示例:select top 10 name,age,sex from ( ...

  9. 工欲善其事必先利其器--------搭建Android平台

    工欲善其事必先利其器--------搭建Android平台 1.1            安装JDK 在Eclipse的开发过程中需要JDK或JRE的支持,否则会报错. (1)     下载JDK(建 ...

随机推荐

  1. Xcode7 iOS9网络配置

    iOS9为了增强数据访问安全,将所有的http请求都改为了https,为了能够在iOS9中正常使用地图SDK,请在"Info.plist"中进行如下配置,否则影响SDK的使用. & ...

  2. 《javascript设计模式》--接口

    关于javascript设计模式书中的接口,记录如下 //TODO  增加了一个判断条件,可以只在生产环境中调用 接口var Interface = function(name,methods){ i ...

  3. PHP扩展开发(1)-创建基础框架

    生成PHP扩展开发的基础框架.   一.Linux下   $>cd ~/{php源码}/ext $>./ext_skel --extname=simple   Creating direc ...

  4. 用PHP删除文件操作unlink

    使用unlink要注意的是$filename的值,要用的是本地绝对地址.比如"c:\aaa\a.jpg",不能用相对地址比如:"../aa.jpg",那么如果在 ...

  5. Python一路走来 线程 进程

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...

  6. C 语言字符 和字符串输出

    int main(void){ char ch; char str[80]; printf("Input a string: ");    //先输入字符串 gets(str);/ ...

  7. hadoop SQL使用

    转载自:http://slaytanic.blog.51cto.com/2057708/782175 Hive 是facebook开源的一个基于hadoop框架的查询工具,也就是说,需要用hive的话 ...

  8. Java学习笔记--HashMap中使用object做key的问题【转】

    在HashMap中,如果需要使用多个属性组合作为key,可以将这几个属性组合成一个对象作为key.但是存在的问题是,要做get时,往往没办法保存当初put操作时的key object的referenc ...

  9. ubuntu 下GIT的安装

    linux下软件的安装方式有多种,最简单的莫过于从软件中心直接安装了或者用命令行直接安装 sudo apt-get install git 但是这样的安装却使我们体会不到最新版本的功能,如果我们想要体 ...

  10. Powershell 设置数值格式 1

    设置数值格式 1 6 6月, 2013  在 Powershell tagged 字符串 / 数字 / 文本 / 日期 / 格式化 by Mooser Lee 格式化操作符 -f 可以将数值插入到字符 ...