我知道这个问题是基于一种非常古老的编程语言,并且也是基于数据库设计的一些不良实践,但我希望得到一些指导,因为我的VBScript不是最新的,而且在我的工作中我我无法更改我的数据库结构或脚本语言。
我正在开发一个网页,该网页从最初在一个表中包含所有数据的数据库中获取数据。但是,我工作的数据库管理员决定将大表分成许多较小的表。我们的网页包含一个带有点数据的在线地图,该数据在新页面中显示找到的每个点的数据表。连接到数据库的代码最初看起来像这样:
sql_select = "SELECT * FROM table_name WHERE master_id='"&key&"'"
Set rs = Conn.Execute(sql_select)
此代码适用于它的用途。但是,现在主表已被分为七个子表,我需要一个代码来选择所有表中的所有数据,然后根据它们的主ID进行过滤。
我觉得我理解如何使这项工作的理论(我不是计算机科学专业,所以这对我来说仍然有点陌生),而且我需要实现一个联盟。我的主要问题是在创建这个脚本时处理VBScript / ASP的语法,因为看起来我尝试的一切都不起作用。
有人可以借给我一些指导吗?非常感谢!
答案 0 :(得分:3)
听起来你真正需要的是一个JOIN而不是一个UNION。 JOIN将来自多个地方的数据粘合在一起,而UNION将多行数据粘合在一起,形成更多行:
在这种情况下,您有一个主表和几个子表。为了示例,我假设表格如下:
Table Columns
---------------------------
MasterTable MasterId, M1, M2, M3
SubTableA SubTableAId, MasterId, A1, A2, A3
SubTableB SubTableBId, MasterId, B1, B2, B3
因此,如果您想要检索列M1-3和A1-A3,那么您可以将MasterTable中的列与SubTableA上的列连接,它们具有匹配的MasterId值:
SELECT *
FROM MasterTable MT
INNER JOIN SubTableA STA ON MT.MasterId = STA.MasterId
MT和STA是别名,所以当我们澄清我们所指的两个主id中的哪一个时,我们不必输入整个表名。
如果我们只想要一个特定主ID的值,我们可以在最后添加一个where子句:
SELECT *
FROM MasterTable MT
INNER JOIN SubTableA STA ON MT.MasterId = STA.MasterId
WHERE MT.MasterId = ?
如果我们需要其他表中的列,我们也可以加入这些表:
SELECT *
FROM MasterTable MT
INNER JOIN SubTableA STA ON MT.MasterId = STA.MasterId
INNER JOIN SubTableB STB ON MT.MasterId = STB.MasterId
WHERE MT.MasterId = ?
我们正在指定INNER JOIN,因为我们只希望在所有三个表中存在匹配值的情况下返回记录。如果SubTableB在某些时候只有每个主id的值,那么我们想要切换到LEFT JOIN或LEFT OUTER JOIN,这将告诉数据库从连接的LEFT侧返回我们的列,即使没有匹配右侧可用的列。
因此,要在我们可能并不总是拥有SubTableB记录但仍想要Master和SubTableA列的情况下获取所有列:
SELECT *
FROM MasterTable MT
INNER JOIN SubTableA STA ON MT.MasterId = STA.MasterId
LEFT JOIN SubTableB STB ON MT.MasterId = STB.MasterId
WHERE MT.MasterId = ?
如果有可能在一个SubTable中有一个MasterId的多个记录,那么将返回与每个可能的JOIN条件匹配的表行组合的行。
因此,如果我们在MasterTable中有一个ID为5的记录,SubTableA中有1个主ID为5,而SubTableB中有3个id为5,那么我们实际上会收到3行,每个1个MasterTable和SubTableA值与SubTable3值的组合。因此,在客户端,您需要能够处理重复的值/行,或者拆分查询以分别从SubTableB执行查询。
您提供的代码虽然是示例,但有两个缺点。一,因为你将参数连接到数据库字符串中,该字符串中的特殊字符可能会破坏您的SQL语句,或者如果您从表单POST,Querystring等中检索该值,那么最终用户实际上可以注入一个SQL语句进入要在数据库上运行的变量(可能丢弃有价值的记录,操纵数据库,甚至可能将特洛伊木马或可执行文件上传到服务器,具体取决于权限级别)。 第二个缺点是执行这样的字符串有潜在的缺点。根据您的数据库引擎,您可以从隐式类型转换,缺少计划缓存等方面获得较小的性能命中,因为该语句是作为非参数化字符串提供的。
要解决这些问题,您应该研究使用参数化SQL语句或为语句创建存储过程并使用参数化值调用它。 ADODB对象支持参数:
Dim yourKeyValue : yourKeyValue = 5
Dim objConn, objCommand, rsResults
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open("Your connection string")
Set objCommand = Server.CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConn
objCommand.CommandText = "YourStoreProcName"
objCommand.CommandType = 4 'stored proc type/enum
objCommand.Parameters.Append objCommand.CreateParameter("Key", 3,1,,yourKeyValue)
set rsResults = objCommand.Execute()
有关参数和常量的更多信息:http://www.w3schools.com/ado/met_comm_createparameter.asp
有关CommandType的更多信息:http://www.w3schools.com/ado/prop_comm_commandtype.asp
您可以更改SQL字符串的命令文本而不是存储过程,并使用?标记作为您定义的参数的占位符。
真正快速清理一下。
您可能希望指定实际要返回的列的列表,而不是为查询指定*。这样可以减少通过网络传输的数据量,只需要告诉数据库您需要的内容,这样就无需预先查找字段名称,这样可以减少您的一些混乱。记录集对象(例如,您可能会有相当多的主id列)。
正如Dee在回复中提到的那样,你可能应该包括那些改变了数据库的人,但是我认为你不想只是将它们转移到他们的圈中,因为你会想要了解它为什么以及如何工作,否则试图进行其他更改或维护应用程序将比现有的更难。
答案 1 :(得分:0)
数据库管理器将表拆分,告诉他们您需要一个新的SQL语句来替换您拥有的SQL语句。由于他们知道新的结构,他们可以在几分钟内为您编写。