连锁创建分店数据库方法,连锁分店数据库
连锁软件中,数据库结构不外两种,一种是所有数据都放同一个数据库,包括总部,另一种是总部独立数据库,每个分店一个数据库,而我常用的就是独立的数据库。
这两种方法各有优势,数据放同一个数据库,各分店之间数据进行交互时会非常方便,有统计之类的,也是直接在数据库上操作,没那么多麻烦,不好的地方就是,数据一多,不便于维护,也得去考虑分页等问题。而第二个方法就是刚上和第一个的好坏相反,但是我觉得分开的话数据会非常清晰,维护方便,当然这只是针对我们软件数据库之间交互不多的情况,可能有的数据库之间交互数据比较频繁,就是用第一个方法,没有什么维护问题,也会选择第一,各有好坏,看各人使用。
独立数据库就得处理创建分店时怎么创建数据库的问题,因为软件是一直在更新的,也就是数据库也是一直更新,所以创建分店数据库,也必须是灵活的。
(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
} 一、连锁企业选址困惑:缺少规范选址成扩张难题
众所周知,选址是连锁门店成功关键的因素,业内有句名言:“门店最重要的是什么。第一是选址,第二是选址,第三还是选址”,可见选址对于连锁企业的重要性。成功的选址系统是连锁企业核心竞争力之一,但受专业及经验限制,国内连锁 企业 在选址的成功率上一直不高,通过 咨询 及接触,我们总结多数连锁 企业 在选址主要存在以下三个层面的困惑:
1 选址凭感觉,没有科学依据,风险非常大。2 成熟商圈店址很难获得,缺少投资收益预测,导致决策失败。3 缺少系统和规范。选址成为扩张时最大难题。
第一种选址凭感觉的情况常出现中小连锁企业,企业老板凭多年经验和直觉来判断店址。往往说不清楚道不明,成败多归咎风水问题。说起自身选址经验,多半是有缘 或有感觉,没有科学依据,风险非常大。曾经有这样的故事,有位美体连锁的女老板介绍自己选店经验时自豪地说:“站在那里闻一下空气,就知道能不能开店。” 结果在深圳发展时连开三家都失败了。另有位 企业 老总谈到他选址经验时说,就到小偷多的地方去 开店 ,结果标准完全不可量化,更多的门店老板在选址的时候凭的是自己的主观经验,凭感觉来投资,由于没有科学根据,其风险非常大,碰运气成分居多。
第二种情况的连锁企业已有一定的选址标准和经验,也注重有策略选址,占据有利位置。但往往旺铺是一铺吃三代,很少转手,成熟商圈的店址更是千金难求,租金、 押金高昂,选择店址时如不能准确预测投资收益,租金成本高于本行业利润率,将导致门店经营失败。另有一种类型,某些连锁 企业 为了降低成本或避开强势竞争实现“农村包围 城市 ”策略,选择次商圈进行布点,也常因不能科学、准确地预测商圈成熟时机而沦为填坑或为人作嫁的下场。以东方家园建材超市在广州的选址为例,作为在华南地区 开设的第一家大型建材家居连锁店,东方家园2004年选址芳村时,选择在城乡结合部的未成熟商圈发展,原预期可获得周边楼盘未来发展带来增长收益。但由于 选址过于偏僻,周围都是批发市场,消费层次较低,客流量太少。整个市场至少需要2至3年的投入培育才能修成正果,选址先天不足加之经营手法上的缺陷,在辛 苦煎熬1年多又歇业7个月之后,芳村店最终无奈地被百安居接管。
连锁业必须进行快速扩张,以此来降低运营成本,连锁 企业 在进入规模扩张时常出现第三种情况,由于没有建立和完善选址标准及规范,缺少组织和系统,一旦批量 开店 选址,人员分身乏术,找不到想要店址,扩张计划不得不一再延迟,选址最终成为扩张战略最大阻碍,这里有代表性的案例是连锁药店排名第一的老百姓大药房,其 进驻北京之后,在经过了6人拓展团队两年的“扫街”选址、三任总经理由此下课之后,才终于在北京开出了第二家店,延误了发展的时机。
二、成功案例分析:科学的选址流程和严密的审批制度
以上谈到的企业选址困惑主要都源于缺少科学、完备的选址标准和系统,如何构建成功的选址系统就成了连锁 企业 成功的秘诀。跨国连锁巨头如沃尔玛、家乐福、麦当劳、肯德基等经过了几十年的发展,在选址时都形成了一套十分科学、严谨的选址系统,对 城市 、建筑设施、周边环境、道路交通、人口密度、人口结构、购买力等都做出定量分析,在此基础上进行商圈分析及 开店 测算,因此选址成功率非常高,其经验值得我们借鉴。以肯德基为例,肯德基目前在世界拥有连锁店数约为14000多家,在中国短短时间就开出近2100多家 门面,其选址投资成功率几乎是百分之百,其成功经验归纳下来有两个方面,
1 建立了科学的选址流程与标准。通常肯德基进......余下全文>>
但是,像零售行业的专卖店、连锁超市或批发商这些企业,收集客户资料相对比较困难,必须运用一些技巧和方法才能成功地建立客户数据库。 1.通过一定的方式和方法,让所有和你接触的客户留下关键性资料 工作人员应该采取客户容易接受的方法,请客户留下资料。为了让客户容易接受,销售人员可以非常客气地列出留下资料对客户的好处,以及保密协议,不要让客户反感,而是让客户产生信任感。 这种数据来源建立起来的客户列表,随着客户情况发生变化,原来列表的价值就显得大打折扣了。所以,企业应该利用数据库管理工具(比如易智数据库营销系统中客户数据维护工具)在固定的时间间隔内更新数据库,保持数据库效率的稳定。 2.通过展会、营销活动等收集资料 公司可以通过举办产品展览会等营销活动来收集参加者的资料,或者举办与自己产品有关的一些娱乐性的营销活动,通过回收答卷来收集参赛者的资料。通过回收答卷收集资料是一种非常易于操作的方法。因为,在问卷上设有住址、姓名、年龄、职业等栏,收集这些问卷自然就可以获取客户列表建立数据库。 3、通过优惠券、折扣券、抽奖活动等方法收集资料 利用优惠券和抽奖活动是零售行业常用的方法,企业会将优惠券折扣券赠送给购买额在一定金额以上的客户,客户在使用这些优惠券时,必须在填写姓名、年龄、联系方式等。而抽奖活动的效果可能会更加准确,抽奖活动企业可以要求客户填写关键性的资料,比如姓名、联系方式等等,因此,使用这些方法自然可以建立有效的数据库。 4、不同行业间的名单交换 例如,服装店和化妆品店交换各自的客户名单,各自向双方的客户销售产品,因为两者都以年轻女性为对象。这种互换客户的方法,分别建立数据列表,而又不引起双方的竞争,达到双营销效果。 5、客户推荐客户,建立更有效的数据库 客户之间互相推荐,本身会带有一定的信任度,建立的数据列表会更为有效。如,汽车销售公司也可以准备一些精美的吸引人的礼物赠送给那些介绍别人来购买的客户。保险公司更愿意采用以下方法:只在与某个客户订下一份保单,就可以通过这个客户得到其他准客户,例如,其亲友、同事等。这种经由保户介绍的潜在客户,一般是效率最高的潜在客户。 6、向专业的列表公司购买 已经有专门提供各行业、各类别列表的公司,这些公司是客户列表的一个最重要的来源。 在购买或租借列表时,一定要根据企业的实际情况,选择最合乎企业要求条件的列表。 如果列表中某人以前曾与你接触过或购买过企业的产品,那这个人的名字与联系方式对企业就很有价值。通常,将产品的资料寄给企业自己建立的列表中的客户要比寄给来自别处的客户列表上的人的效果高出三倍甚至三倍以上。即使这些外借来的列表与你自己列表的性质与背景十分相近,也无法获得和自己建立的列表一样的效果。 按照数据库营销的经验来说,当企业从外部租借或购买一份列表后,必须根据自己公司的实际情况,利用数据库营销系统对这份列表进行整理,以避免不必要的重复和无谓的资源浪费。所以,当企业购得一份列表时,不是所有的客户都很有用,必须加以整理删减,进行细分,使数据库营销活动的效果更显著。