从VBScript / ASP中的多个表中进行选择

时间:2011-12-07 19:18:18

标签: sql asp-classic vbscript

我知道这个问题是基于一种非常古老的编程语言,并且也是基于数据库设计的一些不良实践,但我希望得到一些指导,因为我的VBScript不是最新的,而且在我的工作中我我无法更改我的数据库结构或脚本语言。

我正在开发一个网页,该网页从最初在一个表中包含所有数据的数据库中获取数据。但是,我工作的数据库管理员决定将大表分成许多较小的表。我们的网页包含一个带有点数据的在线地图,该数据在新页面中显示找到的每个点的数据表。连接到数据库的代码最初看起来像这样:

sql_select = "SELECT * FROM table_name WHERE master_id='"&key&"'"
Set rs = Conn.Execute(sql_select)

此代码适用于它的用途。但是,现在主表已被分为七个子表,我需要一个代码来选择所有表中的所有数据,然后根据它们的主ID进行过滤。

我觉得我理解如何使这项工作的理论(我不是计算机科学专业,所以这对我来说仍然有点陌生),而且我需要实现一个联盟。我的主要问题是在创建这个脚本时处理VBScript / ASP的语法,因为看起来我尝试的一切都不起作用。

有人可以借给我一些指导吗?非常感谢!

2 个答案:

答案 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执行查询。

VBScript SQL代码

您提供的代码虽然是示例,但有两个缺点。一,因为你将参数连接到数据库字符串中,该字符串中的特殊字符可能会破坏您的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语句。由于他们知道新的结构,他们可以在几分钟内为您编写。

相关问题