` 的数据行。每个 ‘v’ 值引用一行数据,每个 ‘w’ 值引用行中的一个字段。
在内层循环结束时,代码会为 Internet Explorer 和非 IE 浏览器进行分支,以避免使用‘setAttribute’ JavaScript 命令,因为该命令在此上下文中与 IE 结合使用时在设置字段的样式/背景和边框属性方面存在问题。
在函数末尾,‘`fxheaderInit()`’ 和 ‘`fxheader()`’ 函数实现了固定表头和滚动数据行,以实现用户在表格中滚动时的效果。
function setTable(tblId,tempArray)
{
var clTable = document.getElementById("contentLines");
clTable.display = "block";
var vsTable = document.createElement('TABLE'); // Set up table structure
vsTable.setAttribute("id",tblId);
vsTable.setAttribute("border","1");
vsTable.setAttribute("cellpadding","2");
vsTable.setAttribute("cellspacing","0");
vsTable.setAttribute("class","mt");
vsTable.setAttribute("style","width:750px;background:#F5F5DC;
border:1px solid lightgray;color:#000080;
font- weight:bold;");
clTable.appendChild(vsTable);
var vsTBody = document.createElement('TBODY');
vsTable.appendChild(vsTBody);
var tbody = document.getElementById(tblId).
getElementsByTagName('tbody')[0];
lineNum = 0;
for (v=0;v<tempArray.length;v++) // Loop through rows
{
SEE LOOP ON NEXT PAGE
}
fxheaderInit(tblId,250,1,0); // Set up and implement
fxheader(); // fixed header scrolling
}
for (v=0;v<tempArray.length;v++) // Loop through rows
{
if (v == 0) {Color = "#dddddd";}
else // Switch alternate row
{ // background colors
fontW = "normal";
setColor(lineNum);
}
var row = document.createElement('TR');
tbody.appendChild(row);
lineArray = tempArray[v];
for (w=0;w<lineArray.length;w++) // Loop through fields
{
var cellW = "cell"+w;
if (v == 0) cellW = document.createElement("TH"); // Create headers
else cellW = document.createElement("TD"); // Create data rows
space = " ";
if ((lineArray[w]*1) > 99) {space = "";}
else if ((lineArray[w]*1) < 10) {space = " ";}
if (v > 0) cellW.innerHTML = space+lineArray[w];
else cellW.innerHTML = "<a href='javascript:
arraySort("+w+");' // Sort by
style='color:#000080;cursor:hand;cursor: pointer; // column
text-decoration:none;'>"+space+lineArray[w]+"</a>"; // contents
if (tblId == "dataTable");
{
if (w == 0) {cellW.setAttribute("class","firstTD");}
else cellW.setAttribute("class","otherTD");
if (v == 0) // Set up headers
{
cellW.setAttribute("class","header");
cellW.setAttribute("id","col"+w);
cellW.setAttribute("onmouseover","
style.cursor='hand';style.cursor='pointer';");
}
}
if (browser == "Internet Explorer") // Branch for IE
{
cellW.style.cssText="background:"+Color+
";border:solid #d3d3d3 1px;font-size:13px";
}
else cellW.setAttribute("style","background:"+Color+";
border:solid #d3d3d3 1px;font-size:13px;");
row.appendChild(cellW);
}
}
表排序代码如下所示,它对包含文本数据(字母和数字形式)的列执行内存数组排序。通过单击列标题对列内容进行排序,每次单击表头时按升序和降序交替排序 - 请参阅 www.web2ria.com/dbBrowse.html。
function arraySort(sortCol)
{
var header = vitalSignsArray.shift(); // Remove Headers
if ((sortCol == 5) || (sortCol == 2))
{
setCol(sortCol,0); // setCol() handles text
} // with "/" or "-"
else
{
if (typeof vitalSignsArray[0][sortCol] == 'string')
{z = vitalSignsArray.naturalSort(sortCol);} // Sort alphabetical data
else z = vitalSignsArray.deepsort(sortCol); // Sort numeric data
}
results = "";
if (direct == "Asc") direct = "Desc"; // Switch next sort direction
else direct = "Asc";
document.getElementById("contentLines").innerHTML = "";
if ((sortCol == 5) || (sortCol == 2)) setCol(sortCol,1);
vitalSignsArray.unshift(header); // Replace headers
setTable("dataTable"); // Build HTML <table>
}
此示例中的排序使用数组 ‘`vitalSignsArray`’ 作为数据源,`setTable()` 函数也使用此数组来填充 HTML 表格。
下一页的 ‘`deepSort()`’ 函数处理数字列的排序。
Array.prototype.deepsort= function()
{
var i, order=arguments, L=order.length, tem;
return this.sort(function(a, b)
{
i= 0;
while(i < L)
{
tem= order[i++];
var ao= a[tem] || 0, bo= b[tem] || 0;
if(ao== bo) continue;
if (direct == "Asc") return ao> bo? 1: -1;
else return bo> ao? 1: -1;
}
return 0;
});
}
下一页的 ‘`naturalSort()`’ 函数处理字符串列的排序。
Array.prototype.naturalSort= function()
{
var a, b, a1, b1, rx=/(\d+)|(\D+)/g, rd=/\d+/;
return this.sort(function(as, bs)
{
a= String(as).toLowerCase().match(rx);
b= String(bs).toLowerCase().match(rx);
while(a.length && b.length)
{
a1= a.shift();
b1= b.shift();
if(rd.test(a1) || rd.test(b1))
{
if(!rd.test(a1)) return 1;
if(!rd.test(b1)) return -1;
if(a1!= b1)
{
if (direct == "Asc") return a1-b1;
else return b1-a1;
}
}
else if(a1!= b1)
{
return a1> b1? 1: -1;
}
}
return a.length- b.length;
});
}
从“Select Database”下拉框中的一个选项中选择一个数据库,当选择更改时,将调用函数 ‘`dbSel()`’,方式与以下伪代码类似:
<select id="dbSel" onChange="if (this.value != 0) dbSel(this.value);">
<option value=0 selected>Select Database</option>
<option value="One Database">One Database</option>
<option value="Another Database">Another Database</option>
<option value="Etc."> Etc.</option>
</select>
函数 ‘`dbSel`’ 的代码显示在下方。
function dbSel(dbNum,startRec,recNum)
{
var dbSel;
if ((startRec == "") && (recNum == ""))
{
startRec = 0;
recNum = 1000;
}
document.getElementById("dbSelFrame").style.visibility = "visible";
dbSel = "queryDB.php?dbSel="+dbNum +
"&startRec="+startRec+"&recNum="+recNum;
document.getElementById("dbSelFrame").src = dbSel;
}
在此函数中,选定的数据库被传递到 queryDB.php,该文件通过更改 `
在 dbBrowse.html 中有函数 ‘`fieldSel()`’ 和 `tableSel()`,它们都通过 `` 源页面 queryDB.php 中的 JavaScript 代码片段以以下方式调用:
<select onChange=parent.tableSel('databaseName’,this.value);></select>
dbBrowse.html 中 `tableSel()` 的代码如下:
function tableSel(dbSel,tableSel)
{
if (tableSel != 'selectTable')
{
document.getElementById("dbSelFrame").src =
"queryDB.php?dbSel="+dbSel+"&tableSel="+tableSel;
}
}
这里,`` 源文件 queryDB.php 会使用新参数重新加载。
并且 dbBrowse.html 中的 `fieldSel()` 函数通过单击 queryDB.php 中的按钮来调用,类似于以下伪代码所示:
<input type='button' onclick=parent.fieldSel('databaseName'); value='Run Query'>
dbBrowse.html 中的 ‘`fieldSel()`’ 函数具有下一页中的代码。
function fieldSel(dbSelLocal)
{
if (document.getElementById("distUn").checked == true)
{
var distinctSQL = 1;
}
else var distinctSQL = 0;
var myIFrame = document.getElementById('dbSelFrame');
var mapStr = myIFrame.contentWindow.mapStr;
var contentStr = myIFrame.contentWindow.columnSelect;
var whereField = myIFrame.contentWindow.whereStr;
var orderStr = myIFrame.contentWindow.orderStr;
var startRec = myIFrame.contentWindow.startRec;
var recNum = myIFrame.contentWindow.recNum;
var table = "";
table = myIFrame.contentWindow.table;
tableSelected =
myIFrame.contentWindow.document.getElementById('db'+dbSelLocal);
table = tableSelected.options[tableSelected.selectedIndex].text;
if ((contentStr != "undefined") && (contentStr != ""))
{
if (contentStr.indexOf(".") > 0)
{
var tempPos = contentStr.indexOf(".");
table = contentStr.substring(0,tempPos);
}
}
var tempSrc = "queryDB.php?startRec="+startRec+
"&recNum="+recNum+
"&whereStr="+whereField+
"&mapStr="+mapStr+
"&orderStr="+orderStr+
"&dbSel="+dbSelLocal+
"&distinctSQL="+distinctSQL+
"&sqlSelect="+contentStr+
"&tableSel="+table;
document.getElementById("dbSelFrame").src = tempSrc;
}
‘`myIFrame`’ 变量用于直接访问 `` queryDB.php 文件中的 JavaScript 部分所需的变量值。
当然,queryDB.php 也可以使用 ‘location.href’ JavaScript 命令直接从自身加载。但这种方法演示了 `` 环境中的父子通信。
queryDB.php
源页面 `` queryDB.php 是一个单一页面,负责处理来自父级 dbBrowse.html 页面的所有可选数据库的查询。代码因 SQL 版本不同而异,因为 MySQL、Microsoft SQL Server 和 ODBC 使用的语法不同,并且它们格式化返回结果的方式也不同。
代码按不同数据库的节进行划分。为了使节操作清晰,并且由于各种数据库供应商 SQL 版本之间的差异,‘通用’操作并未分离成通用函数。然而,一些真正通用的适用于所有节的 JavaScript 函数在适当的地方被使用,例如创建带有可滚动表格的固定表头的函数。
每个节在不同的 Internet URL 上连接并登录到各个数据库,然后运行默认查询,并返回结果,这些结果显示在一个带有固定表头的可滚动表格中。默认查询返回的结果以相似的布局显示在一个页面中,无论显示的是哪个数据库。
页面顶部区域的布局(下面第 5.6 图所示)允许通过使用 HTML `` 下拉框为每个数据库选择 SQL 查询。这些下拉框会自动填充适用于所选数据库和表而不适用于其他数据库和表的选项,例如每个特定数据库和表的字段名称。
图 5.6 - queryDB.php 中常用控件的布局
页面下半部分的布局取决于数据库,其中包含一个 HTML 表格,每个数据库表列对应一个列,表头与数据库表列/字段头名称相同。HTML 表头是固定的,表格行是可滚动的。
图 5.7 - 典型的 queryDB.php 数据表
表列标题与下拉 `` 框中的选项匹配,这些框允许选择数据库表字段用于 SQL 查询,并在“Select Field”框中添加了“*”选项,以便一次单击选择所有字段。“Select Table”`` 框位于前一页数据库选择下拉框的正下方,显示特定数据库的所有表。
当从表下拉列表中选择新表时,queryDB 会自动重新加载,并对该表运行“`SELECT * FROM tableName`”形式的默认查询,并显示新选定表的字段信息。但是,当选择单个字段来构成查询时,只有在单击“Run Query”按钮时才会运行查询。
具有“Select Field”默认选项的 `` 下拉框允许一次选择一个字段用于 SQL 查询,并且所选字段显示在“Fields Selected”框中。通过单击“*”选项,可以一次单击选择所有字段。如果需要移除选定的字段,可以通过双击“Fields Selected”框中的条目来移除。
查询可以通过“Where Select Field”和条件下拉框进行细化,这些下拉框显示“=”、“LIKE”、“<”、“>”、“<=”和“>=”选项。并将在相邻的文本框中输入表格字段的值,通过从表格复制粘贴,或通过输入值。
在指定“Where”子句后,每当焦点转移到另一个页面元素时,它会自动输入到“WHERE Clauses Selected”框中。例如,单击“Run Query”按钮,或在“Select Field”下拉列表中选择新选项。
通过“AND/OR”下拉列表中的“AND”或“OR”选项以及输入新的“Where”子句来选择其他“Where”子句。与“Fields Selected”框一样,可以通过双击来移除已选定的不需要的“WHERE Clauses Selected”项。
Sort By “Select Field”下拉框允许选择一个用于对查询结果进行排序的字段,并通过单击相应的单选按钮来选择 Asc 或 Desc 顺序。
图 5.8 - 完成的查询,执行前
当查询已成功构建后,通过单击“Run Query”按钮来执行它,这将重新加载 queryDB.php 页面以运行新的查询参数。然后将在表格中显示所选列的 SQL 查询结果。如果在“Select Field”下拉列表中至少有一个字段未被选中,将弹出警报框提示错误。
如果选择的数据库是“MS SQL Server Northwind”,还会显示一个 Geocoding 下拉框。这允许在选择“Customers”表时选择用于映射的字段。
默认情况下,在“Customers”表中的 Geocoding 通过双击“Address”字段运行,“Address”、“City”、“Region”、“PostalCode”和“Country”字段值将用于在单独的窗口中显示地图。请参见下面的第 5.9 和 5.10 图。
图 5.9 & 5.10 - MS SQL Server Northwind 数据库中的 Geocoding
3 种不同数据库类型的连接字符串和 SQL 查询看起来像下面几页描述的 PHP 伪代码。
MS SQL Server
$MSSQLconnect = // Replace userName and password with actual ones
mssql_connect("205.209.97.138","userName","password");
$dbName = "Northwind”;
$objDB = mssql_select_db($dbName);
表名是通过 SQL 查询从数据库中获取的
$strSQL = "SELECT name FROM sys.tables";
$objQuery = mssql_query($strSQL);
并且“Table Names”下拉列表是通过循环填充的
while($objResult = mssql_fetch_array($objQuery))
{
$tablename=$objResult[0];
$tempStr = "<option value='".$tablename;
if ($tablename == $table) // $table is the selected table
{
$tempStr = $tempStr."' selected";
}
else $tempStr = $tempStr."'";
print $tempStr.">$tablename</option>";
$tableArray[$count] = $tablename;
$count++;
}
字段标题下拉列表是从 SQL 查询生成的‘`$fieldArray`’数组填充的
$query = "SELECT COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME='tableName'";
// Replace tableName with real name
$result = mssql_query($query,$MSSQLconnect);
$rowCount = 0;
while ($get_info = mssql_fetch_row($result))
{
foreach ($get_info as $field) $fieldArray[$rowCount] = "$field";
$rowCount++;
}
实际数据库查询是通过以下 PHP 伪代码构建的
if ($sqlSelect != "")
{
if ($whereStr == "undefined") $whereStr = "";
$tempSel = "SELECT ";
if ($whereStr != "")
{
$whereStr = str_replace("\%27","'",$whereStr);
}
$query = "$tempSel TOP $recNum $sqlSelect";
$query = "$query FROM $table $whereStr";
if (($orderStr != "undefined") && ($orderStr != "null") &&
($orderStr != "")) $query = $query.$orderStr;
}
else $query = "SELECT TOP $recNum * from $table";
$query = str_replace('%27',"'",$query);
$result = mssql_query($query,$MSSQLconnect);
if ($result != "") $numrows = mssql_num_rows($result);
else $numrows = 0;
以下变量都从 dbBrowse.html 传递到 queryDB.php:
$sqlSelect
- SQL 查询的“SELECT”部分 $recNum
- 要显示的记录数$whereStr
- SQL 查询的“WHERE”部分$orderStr
- SQL 查询的“ORDER BY”部分$table
- SQL 查询中使用的表名
最终查询可能如下所示:
SELECT TOP 5 CompanyName,City FROM Customers
WHERE Country = ‘USA’
AND ContactTitle = ‘Owner’;
此查询的网页选择如下所示:
图 5.11 - MS SQL Server 查询选择屏幕截图
结果如下:
图 5.12 - MS SQL Server 结果屏幕截图
请注意,SQL Server 对使用 SQL 对列进行排序有一些限制,您可能希望实现通过单击列标题启动的排序过程作为替代方案。
MySQL
$MySQLconnect = mysql_connect("74.50.94.228","userName","password");
// Replace the URL, userName, and password with actual ones, and note that the
// URL can be the long-form descriptive URL, e.g. ‘genome-mysql.cse.ucsc.edu’.
$dbName = "world";
// Replace database name with actual one
mysql_select_db($dbName,$MySQLconnect);
Table names are found from the PHP function
$tablelist = mysql_list_tables($dbName);’
在下面的伪代码中,正在查询的表名存储在从 dbBrowse.html 传递到 queryDB.php 的变量 `$table` 中。包含特定表字段名的 `$result` 变量通过以下查询找到:
$query = "SELECT COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_SCHEMA='".$dbName."' AND
TABLE_NAME='".$table."'";
$result = mysql_query($query,$MySQLconnect);
循环填充“Select Field”下拉列表并生成 `$fieldArray`,如下一页所示。
$rowCount = 0;
while ($get_info = mysql_fetch_row($result))
{
foreach ($get_info as $field)
print "<option value='$table.$field'>$field</option>\n";
$fieldArray[$rowCount] = "$field";
$rowCount++;
}
从选定的表中获取数据的数据库查询是通过以下 PHP 代码构建的:
if ($whereStr == "undefined") $whereStr = "";
$tempSel = "SELECT ";
if ($whereStr != "")
{
$whereStr = str_replace("%27","'",$whereStr);
}
$query = "$tempSel $sqlSelect FROM $table $whereStr";
if (($orderStr != "undefined") && ($orderStr != "")) $query =
$query.$orderStr;
$query = $query." LIMIT $startRec, $recNum";
$result = mysql_query($query,$MySQLconnect);
以下变量都从 dbBrowse.html 传递到 queryDB.php:
$startRec
- 要显示的第一个记录$recNum
- 要显示的记录数$sqlSelect
- SQL 查询的“SELECT”部分$whereStr
- SQL 查询的“WHERE”部分$orderStr
- SQL 查询的“ORDER BY”部分
对于 MySQL 的“world”数据库,最终查询可能如下所示:
SELECT Name, Continent, Population, LifeExpectancy FROM Country
WHERE Continent = ‘Europe’ AND Population >= 1000000
ORDER BY Population DESC LIMIT 0, 10
实现此查询的选择将在下一页的屏幕截图中显示。
图 5.13 - MySQL 查询选择屏幕截图
结果如下所示:
图 5.14 - MySQL 查询结果屏幕截图
ODBC 文本
$connect = odbc_connect("ODBC_DSN”,"userName","password");
将上面的‘`userName`’和‘`password`’替换为实际的,并且 ODBC DSN
(数据源名称) Text 驱动程序设置为要访问的服务器文件,“SNOMEDCT_CORE_SUBSET_201002.txt”在此处。‘schema.ini’初始化文件与‘SNOMED … ’ .txt 数据文件放在同一位置。‘ini’文件对于竖线(|)分隔的文件“SNOMEDCT_CORE_SUBSET_201002.txt”看起来如下一页所示。
[schema.ini] ColNameHeader=False Format=CSVDelimited MaxScanRows=25 CharacterSet=OEM [snomedct_core_subset_201002.txt] ColNameHeader=True Format=Delimited(|) MaxScanRows=25 CharacterSet=OEM Col1=SNOMED_CID Integer Col2=SNOMED_FSN Char Width 255 Col3=SNOMED_CONCEPT_STATUS Char Width 255 Col4=UMLS_CUI Char Width 255 Col5=OCCURRENCE Integer Col6=USAGE Float Col7=FIRST_IN_SUBSET Integer Col8=IS_RETIRED_FROM_SUBSET Char Width 255 Col9=LAST_IN_SUBSET Char Width 255 Col10=REPLACED_BY_SNOMED_CID Char Width 255
字段标题下拉列表是从默认查询伪代码生成的 HTML 表格的第一条记录填充的,如下所示:
$Query = "SELECT TOP 1000 * FROM
SNOMEDCT_CORE_SUBSET_201002.txt";
$queryexe = odbc_exec($connect, $Query);
odbc_result_all($queryexe,'id="dataTable" class="mt"');
来自‘`dataTable`’ HTML `
` 的数据填充数组变量‘`tableTH`’,如下所示:
var tempTable = document.getElementById('dataTable');
var tableTH = tempTable.getElementsByTagName('th');
并且包含表头的“Select Field”下拉列表(ID 为‘`dbSNOMEDFields`’)是用数组变量‘tableTH’循环填充的,如下所示:
for (h=0; h < tableTH.length; h++)
{
var optn = document.createElement('OPTION');
optn.text = tableTH[h].innerHTML;
optn.value = tableTH[h].innerHTML;
document.getElementById('dbSNOMEDFields').options.add(optn);
}
实际数据库查询是从 queryDB.php 中的 HTML 下拉框中进行的选项构建的,如下所示:
$Query1 = "SELECT TOP $recNum $sqlSelect FROM
SNOMEDCT_CORE_SUBSET_201002.txt";
if (($whereStr != "") && ($whereStr != undefined))
{
$whereStr = str_replace('%27',"'",$whereStr);
$Query1 = $Query1." ".$whereStr;
}
if (($orderStr != "") && ($orderStr != undefined))
{
$Query1 = $Query1." ".$orderStr;
}
$recNum (记录数)
, $sqlSelect (SQL SELECT 语句)
, $orderStr (SQL ORDER BY 字符串)
, 和 $whereStr
(SQL WHERE 子句) 从 dbBrowse.html 传递到 queryDB.php。
参数从 queryDB.php 传递到 dbBrowse.html,然后在 `` 重新加载时作为 URL 参数传回 queryDB.php。
最终查询可能如下所示:
SELECT TOP 5 SNOMED_CID,SNOMED_FSN FROM
SNOMEDCT_CORE_SUBSET_201002.txt
WHERE SNOMED_FSN LIKE '%Asthma%'
ORDER BY SNOMED_CID DESC
在此应用程序中,此查询的选择如下所示:
图 5.15 - ODBC 文本文件查询选择屏幕截图
结果如下:
图 5.16 - ODBC 文本文件结果屏幕
‘SNOMEDCT_CORE_SUBSET_201002.txt’源文件实际上不是逗号分隔值 .csv 文件,因为某些字段包含逗号。因此,分隔符是竖线字符‘|’,ASCII HTML 数字‘|’。
ODBC DSN 必须为此分隔符进行配置。数据文件中的前 3 条记录如下所示(为便于阅读而折叠),第一条记录是列标题(此行后的换行符和空白行也在此处插入以方便阅读)。第二条记录的第二个字段中有一个逗号,在“disorder”和“systemic”这两个词之间。
SNOMED_CID|SNOMED_FSN|SNOMED_CONCEPT_STATUS|UMLS_CUI| OCCURRENCE|USAGE|FIRST_IN_SUBSET|IS_RETIRED_FROM_SUBSET|LAST_IN_SUBSET|REPLACED_BY_SNOMED_CID
38341003|Hypertensive disorder, systemic arterial (disorder)|Current|C0020538|7|3.0865|200907|False|| 55822004|Hyperlipidemia (disorder)|Current|C0020473|7|1.9093|200907|False||
© . All rights reserved.