连锁软件中,数据库结构不外两种,一种是所有数据都放同一个数据库,包括总部,另一种是总部独立数据库,每个分店一个数据库,而我常用的就是独立的数据库。 这两种方法各有优势,数据放同一个数据库,各分店之间数据进行交互时会非常方便,有统计之类的,也
连锁软件中,数据库结构不外两种,一种是所有数据都放同一个数据库,包括总部,另一种是总部独立数据库,每个分店一个数据库,而我常用的就是独立的数据库。
这两种方法各有优势,数据放同一个数据库,各分店之间数据进行交互时会非常方便,有统计之类的,也是直接在数据库上操作,没那么多麻烦,不好的地方就是,数据一多,不便于维护,也得去考虑分页等问题。而第二个方法就是刚上和第一个的好坏相反,但是我觉得分开的话数据会非常清晰,维护方便,当然这只是针对我们软件数据库之间交互不多的情况,可能有的数据库之间交互数据比较频繁,就是用第一个方法,没有什么维护问题,也会选择第一,各有好坏,看各人使用。
独立数据库就得处理创建分店时怎么创建数据库的问题,因为软件是一直在更新的,也就是数据库也是一直更新,所以创建分店数据库,也必须是灵活的。
(Mssql)最早用的的方法:会在总部放一个数据库的备份文件(Bak),每次更新就是覆盖Bak文件,而创建数据库的思路,1.把model数据库备份成model.bak,2.把bak文件还原到model中,3.直接用create database 语句就可以建一个分店数据库了,4.用model.bak还原回model数据库,【注意:创建数据库时,都会以model数据库模版来创建,这里正是利用这个】
这个方法是可以实现创建分店,但是比较笨,每次更新都要在更新文件里加个数据库bak文件,而且数据库都一直在增大,虽然是空数据库,只有表结构等这些东西,但也得8M+,这在更新时带来很多麻烦,于是后面又想到一个方法,在原有基础上改进。
(Mssql)改进的方法:1.在安装软件时,会在mssql server上创建一个模版数据库,这个模版数据库也可以看作一个分店的数据库,软件更新时,会更新这个数据库,更新完会备份这个模版数据库,覆盖总部中的Bak文件,后面创建分店时怎么创建数据库的还是没变,和上面一样。这里改进的主要就是数据库模版问题,这样做的话,就不用每次更新带上数据库文件了。
最初的软件就一直使用这个方法到现在。
最近有一套新软件,在数据库的设计上又是遇到这问题,我总觉得改进过的方法也不是很方便,于是又想到下面的改进方法。
1.保持使用模版数据库,模版数据库随分店的更新一同更新,Bak文件使用不上了,作废。2.在创建分店时,先创建一个空的数据库,然后通过程序读取模版数据库的所有结构到新数据库上执行,简单点说就是通过程序来复制模版数据库的所有结构。
这样就不用再使用Bak那样的笨重文件了,而且数据库可以独立一个服务器,老方法是数据库和软件必须同一个服务器,因为要依赖放在总部里的Bak文件,而现在数据库和软件就可以脱离,模版数据库保护最新,分店创建新数据库复制模版数据库的结构,问题都解决 了。
随带说一下Mysql,因为我们软件是兼容多种数据库的,Mysql也是其中,前期mysql和mssql的思路是一样的,都是通过更新数据库文件,用数据库备份文件来创建新数据库,后面Mysql也改成这种最优的方法:1.软件安装完,自动创建一个模版数据库,2.创建新分店时,会把数据库备份成sql文件,再在程序中修改sql文件中的数据库名称,3.执行sql文件。这里mysql和mssql不一样的地方就是,mssql的复制表结构,必须一个一个去模版数据读出来再在新数据库上执行,而mysql的备份就是导出数据库的所有结构,我们只需要修改一个数据库名称为新的数据库执行。
下面附上C#里复制数据库的方法:
public void InitialData(string ModelDataBaseName, string DataBaseName) { #region 处理表和表数据 string strSql_GetUserTable = string.Format("select * from {0}.dbo.GetUserTable order by id,columnsort ", ModelDataBaseName); DataTable dt_GetUserTable = dbHelper.ExecuteQuery(CommandType.Text, strSql_GetUserTable, null).Tables[0]; if (dt_GetUserTable.Rows.Count > 0) { //id,tablename,columnsort,columnname,tablekey,columndatatype,columndatalen1 //columndatalen2,columndatafloat,allowisnull,defaultdata string tableName = ""; StringBuilder strCreateTableSql = new StringBuilder(); StringBuilder strKeySql = new StringBuilder(); StringBuilder strInsertData = new StringBuilder(); foreach (DataRow dr in dt_GetUserTable.Rows) { if (dr["tablename"].ToString() != tableName) { if (!string.IsNullOrEmpty(strCreateTableSql.ToString())) { if (strKeySql.Length > 0) { strKeySql.Remove(strKeySql.Length - 1, 1); strCreateTableSql.AppendFormat(" PRIMARY KEY CLUSTERED ( {0} )) ON [PRIMARY] ", strKeySql.ToString()); strKeySql.Remove(strKeySql.Length - 1, 1); } else { if (strCreateTableSql.ToString().EndsWith(",")) strCreateTableSql.Remove(strCreateTableSql.Length - 1, 1); strCreateTableSql.Append(" )"); } dbHelper.ExecuteNonQuery(DataBaseName, strCreateTableSql.ToString(), null); dbHelper.ExecuteNonQuery(CommandType.Text, string.Format(" insert into {0}.dbo.{1} select * from {2}.dbo.{1} ", DataBaseName, tableName, ModelDataBaseName), null); } tableName = dr["tablename"].ToString(); strCreateTableSql.Clear(); strCreateTableSql = new StringBuilder(); strKeySql.Clear(); strKeySql = new StringBuilder(); strCreateTableSql.AppendFormat(" create table {0} (", tableName); } strCreateTableSql.Append(dbHelper.GetDataType(dr["columnname"].ToString(),dr["columndatatype"].ToString(), dbHelper.GetInt(dr["columndatalen2"].ToString()), dbHelper.GetInt(dr["columndatafloat"].ToString()), dr["allowisnull"].ToString(), dr["tablekey"].ToString(),ref strKeySql)); } if (!string.IsNullOrEmpty(strCreateTableSql.ToString())) { if (strKeySql.Length > 0) { strKeySql.Remove(strKeySql.Length - 1, 1); strCreateTableSql.AppendFormat(" PRIMARY KEY CLUSTERED ( {0} )) ON [PRIMARY] ", strKeySql.ToString()); strKeySql.Remove(strKeySql.Length - 1, 1); } else { if (strCreateTableSql.ToString().EndsWith(",")) strCreateTableSql.Remove(strCreateTableSql.Length - 1, 1); strCreateTableSql.Append(" )"); } dbHelper.ExecuteNonQuery(DataBaseName, strCreateTableSql.ToString(), null); dbHelper.ExecuteNonQuery(CommandType.Text, string.Format(" insert into {0}.dbo.{1} select * from {2}.dbo.{1} ", DataBaseName, tableName, ModelDataBaseName), null); } } #endregion #region 存储过程、视图、函数、触发器 StringBuilder strSql = new StringBuilder(); strSql.AppendFormat(" select name,type,definition from {0}.dbo.GetUserPV ",ModelDataBaseName); DataTable dt_GetUserPV = dbHelper.ExecuteQuery(CommandType.Text, strSql.ToString(), null).Tables[0]; if (dt_GetUserPV.Rows.Count > 0) { StringBuilder strTest = new StringBuilder(); foreach (DataRow dr in dt_GetUserPV.Rows) { dbHelper.ExecuteNonQuery(DataBaseName, string.Format("{0}", dr["definition"].ToString()), null); } } #endregion }