import com; import fsys; import string.list; import time.ole; class access { ctor( path,param,...){ if(!path) error("请指定数据库路径",2); var connectionString = path; this.dataSourceName = ..string.match( connectionString,"!\w<@@DSN@>\s*\=([^;]+)"); if(!this.dataSourceName){ var ext = ..string.match(path,"[^.]+$"); ext = ext ? ..string.lower(ext); var excelFormat = ({xls="xls";xlsx="xlsx";xlsm="xlsm";xlsb="xlsb"}) [ext]; if( ( ! ..string.find(path,"\;") && !... ) && ( ( param === null ) || ( type(param) == type.table ) ) ) { var tList = ..string.list(,";","=") tList.mixin(param) for i,k,v in tList.each() { if( ( ..string.indexOf(v,";") || ..string.indexOf(v,"=") ) && !..string.match(v,"^\s*%{}\s*$") ){ tList[k] = ..string.format("'%s'",v); } } var _,_,provider = tList.find("Provider"); if( !provider && !tList.find("Driver") ) { var isText = ({csv=1;tab=1;txt=1;asc=1})[ext]; if( ! ( ..fsys.isDir(path) || isText ) ){ if( (excelFormat && excelFormat != "xls") or ( ext == "accdb" ) ){ if(..access.oleDb[["install"]]){ tList.Provider = ..access.oleDb.install(,true); } else { tList.Provider = "Microsoft.ACE.OLEDB.16.0" } } else{ tList.Provider="Microsoft.Jet.OLEDB.4.0"; } } else { tList.Driver="{Microsoft Text Driver (*.txt; *.csv)}"; if(!tList.Extensions && !tList.extensions ){ tList.Extensions = "asc,csv,tab,txt"; } } } elseif( ..string.cmp(provider,"Microsoft.ACE.OLEDB.16.0") === 0 ) { if(..access.oleDb[["install"]]) ..access.oleDb.install(); } if(excelFormat && !tList.find("Extended Properties") ) { var _,_,hdr = tList.find("HDR"); if(!hdr) hdr = "Yes";//第一行作为列名(Header Row Directive) else tList.remove("HDR"); if( excelFormat == "xls" ){ tList["Extended Properties"] = "'Excel 8.0;HDR="+hdr+"'"; } else { var xmlVersion = "12.0";//Xml 格式只存在这一个版本,不能改为 16.0 if( excelFormat == "xlsx" ){ tList["Extended Properties"] = '"Excel '+xmlVersion+' Xml;HDR='+hdr+'"'; } elseif( excelFormat == "xlsm" ){ tList["Extended Properties"] = '"Excel '+xmlVersion+' Macro;HDR='+hdr+'"'; } else { tList["Extended Properties"] = '"Excel '+xmlVersion+';HDR='+hdr+'"'; } } } path = ..io.fullpath(path); if( tList.find("Driver") ){ tList["Dbq"] = path; } else { tList["Data Source"] = path; } connectionString = tostring( tList ); } else { if( param ) { connectionString = ..string.format(connectionString, param,... ); }; var count; for(i,p in { "(D|data S|source\s*)\=\s*(.+?)\;"; "(I|initial C|catalog\s*)\=\s*(.+?)\;"; "(D|database\s*)\=\s*(.+?)\;"; "(Dbq\s*)\=\s*(.+?)\;"; "(DBQ\s*)\=\s*(.+?)\;"; "(dbq\s*)\=\s*(.+?)\;" } ){ connectionString,count = ..string.replace(connectionString,p,function(k,p){ path = ..io.fullpath(p) return ..string.format("%s=%s;", k,path) } ) if(count) break; } } } if( (!this.dataSourceName) && ( !excelFormat ) && ( ! ..io.exist(path) ) ) { var cat = ..com.CreateObject( "ADOX.Catalog") var ok,c = call( cat.Create,cat, connectionString ) cat = null; if(ok) this.connection = c; else { this.connection = ..com.CreateObject("ADODB.Connection"); this.connection.ConnectionString = connectionString; var ok,e = call(this.connection.open,this.connection); if(!ok) return null,"打开数据库连接失败:" + c; } } else { this.connection = ..com.CreateObject("ADODB.Connection"); this.connection.ConnectionString = connectionString; var ok,e = call(this.connection.open,this.connection); if(!ok) return null,"打开数据库连接失败:" + e; } ..com.SetPreferredArrayType(this.connection,0xC/*_VT_VARIANT*/); this._tables = {@{_weak="kv"}} this.connectionString = connectionString; ..table.gc(this,"close"); }; getCatalog = function(){ if( this.catalog ) { return this.catalog; } this.catalog = ..com.CreateObject("ADOX.Catalog") this.catalog.ActiveConnection = this.connection; return this.catalog; }; eachTableObject = function(){ var cat = this.getCatalog(); var next,items,idx = ..com.each(cat.Tables); var tbl; return function(){ idx,tbl = invoke(next,items,idx) if( tbl ) return tbl.getName(),tbl.getType(),tbl; } }; firstTableName = function(dType){ return this.firstTableObject(dType)[["name"]]; }; firstTableObject = function(dType,cache){ var cat = this.getCatalog(); cat.Tables.Refresh(); if(!dType) dType = "TABLE"; for index,tbl in ..com.each(cat.Tables) { if( tbl.Type = "TABLE" ){ if(cache) this._tables[ tbl.Name] = tbl; return tbl; } } }; findTableObject = function(name,cache=true){ if(cache && this._tables[name] ) return this._tables[name]; var cat = this.getCatalog(); cat.Tables.Refresh(); for index,tbl in ..com.each(cat.Tables) { if( tbl.Type = "TABLE" and tbl.Name = name ){ if(cache) this._tables[name] = tbl; return tbl; } } }; existsTable = function(name){ return !!this.findTableObject(name); }; exec = function(sql,...){ if(!sql) error( "参数 @1 必须指定 SQL ,不能是 null 值!",2); if( ... )sql = format(sql,...); var ret,result,recordsAffected = call(this.connection.Execute,this.connection,sql,0,1 | 0x80/*_adCmdText | adExecuteNoRecords*/); if(!ret) error(result,2); return recordsAffected; }; openRecordSet = function(sql,cursorType,lockType,...){ var rs = ..com.CreateObject("ADODB.RecordSet"); ..com.SetPreferredArrayType(rs,0xC/*_VT_VARIANT*/); if( ... )sql = format(sql,...); var ok,err = call(rs.Open,rs,sql,this.connection,cursorType,lockType); if(!ok) return null,err; return _recordSet(rs) }; getRows = function(sql,...){ var rs,err = owner.openRecordSet(sql,,,...); if(!rs) error(err,2); return _getRows(rs,true); }; getTable = function(sql,...){ var data = this.getRows(sql,...); if(data) return _rows2table(data); }; stepQuery = function(...){ return this.getTable(...)[[1]]; }; each = function(sql,...){ var rs,err = this.openRecordSet(sql,,,...); var first = true; if(!rs)error(err,2); return function(){ if(!first) rs.movenext(); else first = false; if( rs.eof ) return; return rs; },function(){ rs.close(); } ; }; createCommand = function(sql,...){ var cmd = ..com.CreateObject("ADODB.Command"); ..com.SetPreferredArrayType(cmd,0xC/*_VT_VARIANT*/); cmd.activeConnection = this.connection; cmd.commandType = ..string.find(sql,"\s\S") ? 1/*adCmdText*/ : 4/*adCmdStoredProc*/; if( ... )sql = format(sql,...); cmd.commandText = sql; cmd.namedParameters = true; var getParameterType = function(value){ var adType,adSize; var t = type(value); select(t) { case "string" { adType = 203/*adLongVarWChar*/ value = ..string.toUtf16(value); adSize = #value/2; } case "number" { adType = 5/*adDouble*/ adSize = 8; } case "buffer" { adType = 204/*adVarBinaryr*/ adSize = #value; } case "boolean" { adType = 11/*adBoolean*/ adSize = 1; } case "null"{ adType = 3/*adInteger*/; adSize = 0; value = ..com.Variant(null); } else { if( ..time.istime(value) ){ adType = 7/*adDate*/; adSize = 8; value = tonumber(..time.ole(value)); } else { error("自动识别类型遇到错误",3) } } } return adType,adSize,value; } cmd[["addParameter"]] = function(name,value,opt=1/*_adParamInput*/,adType,adSize){ var adType,adSize,value = getParameterType(value); var param = cmd.CreateParameter(name,adType,opt,adSize,value); cmd.Parameters.Append(param); return param; }; cmd[["bind"]] = function(parameters){ if( type(parameters) == type.table ){ if( cmd.parameters.Count ){ var p,n,v; for(i=1;cmd.parameters.Count;1){ p = cmd.parameters(i-1); n = ..string.right(p.name,-2) v = parameters[n]; if(v===null){ p.Value = ..com.Variant(null); continue; } if(cmd.commandType != 4){ p.Type,p.Size,v = getParameterType(v); } p.Value = v; } return; } if( cmd.commandType == 4 ){ for(name,value in parameters){ cmd.addParameter(name,value); } return cmd; } //access的参数虽然必须指定正确的名字,但实际上他是忽略名字按SQL中出现的顺序设置参数的 ..string.replace(cmd.commandText,"\@(<:+>|<\w+>)", function(name){ cmd.addParameter(name,parameters[name]); } ) return cmd; } //已废弃,勿用 return { parameters = function(tParam){ return cmd.bind(tParam); } } }; cmd[["executeNoRecords"]] = function(ra,parameters){ cmd.execute(ra,parameters,cmd.adExecuteNoRecords); }; cmd[["executeRecords"]] = function(ra,parameters){ var rs = cmd.execute(ra,parameters); if(rs){ return _recordSet(rs) } }; cmd[["executeStream"]] = function(ra,parameters){ cmd.execute(ra,parameters,cmd.adExecuteStream); }; cmd[["getRows"]] = function(...){ var rs,err = cmd.execute(...); if(!rs) error(err,2); return _getRows(rs,true); }; cmd[["getTable"]] = function(...){ var data = cmd.getRows(...); if(data) return _rows2table(data); }; cmd["stepQuery"] = function(...){ return cmd.getTable(...)[[1]]; }; cmd["each"] = function(...){ var rs,err = cmd.execute(...); var first = true; if(!rs)error(err,2); return function(){ if(!first) rs.movenext(); else first = false; if( rs.eof ) return; return rs; },function(){ rs.close(); } ; }; return cmd; }; setPassword = function(pwd,oldPwd){ return this.exec("ALTER DATABASE PASSWORD %s %s",pwd,oldPwd : "``"); }; beginTrans = function(){ return this.connection.BeginTrans(); }; commitTrans = function(){ return this.connection.CommitTrans(); }; rollbackTrans = function () { return this.connection.RollbackTrans(); }; close = function(){ if(this.connection){ this.connection.close(); this.connection = null; } }; @_meta; } namespace access { _meta = { _get = function(k){ if( ..string.cmp(k,"ad",2) == 0 ){ owner[[k]] = owner.connection[k]; return owner[[k]]; }; } }; escapeId = function(id){ if(type(id)==="table"){ if(#id){ var ret = {} for(i=1;#id;1){ ..table.push(ret,escapeId(id[i])); } return ..string.join(ret,","); } else { var ret = {} for(k,v in id){ if(type(v)!="table") ..table.push(ret,escapeId(k) + " = " + escape(v)); else ..table.push(ret,escapeId(k) + " IN " + escape(v,true)); } return ..string.join(ret," AND "); } } return '[' + ..string.replace(id,"\.", '].[')+ ']' }; escape = function(v,nested){ var t = type(v); if( t = "string" ){ return "'" + ..string.replace(v,"'","''") + "'"; } elseif( t = "number" ){ return tostring(v,,'.'#); } elseif( t = "boolean" ){ return v ? "1" : "0"; } elseif( t = "table" ) { if(..time.istime(v)){ var f = v.format; v.format = "%Y-%m-%d %H:%M:%S"; var ret = "#" + tostring(v) + "#"; v.format = f; return ret; } elseif(#v){ var ret = {} for(i=1;#v;1){ ..table.push(ret,escape(v[i],true)); } ret = ..string.join(ret,","); if(nested) ret = "(" + ret + ")"; return ret; } elseif( v@[["_toSqlString"]] ){ return invoke(v@[["_toSqlString"]],v,'access') } else { var ret = {} for(k,vv in v){ ..table.push(ret,escapeId(k) + " = " + escape(vv)); } return ..string.join(ret,","); } } elseif( t=='buffer'){ return ..string.concat("0x",..string.hex(v,"") ); } return ..string.replace(tostring(v),"\p",""); }; format = function(sql,...) { if( type( ... ) == "table" ){ var param = ...; if(#param){ var i = 0; return ..string.replace(sql,"<\?\?*>|<\@<:+>|<\w+>>", function(name) { if(name[1]=='@'#){ return escape(param[..string.right(name,-2)]) } i++; if( name == "?" ) return escape(param[i]); else return escapeId(param[i]) } ); } return (..string.replace(sql,"\@(<:+>|<\w+>)", lambda(name) escape(param[name]) )); } return ..string.format(sql,...); } formatSqlParameters = format; _getRows = function(rs,rsClose){ var recordCount = 0; var closed = (rs.State == rs.AdStateClosed); var eof = closed || rs.eof; var data = eof ? { @{} } : rs.GetRows(); var fields = {}; var name; for( i=1;rs.Fields.Count ){ var name = rs.Fields(i-1).Name; if(#name){ fields[i] = name; data[ name ] = data[ i ]; } if(!eof){ var _,len = ..table.range(data[ i ]); recordCount = ..math.max(len,recordCount); } } if(rsClose && !closed ) rs.Close(); data@.recordCount = recordCount; data@.fields = fields; return data; } _rows2table = function(data){ var result = {}; var v; var rowCount = data@.recordCount; if(!rowCount) return result; var trim = ..string.trimright; var fields = data@.fields; for(c=1;#data){ var col = data[c]; var name = fields[c]; if(!#name) name = c; if(c>1){ for(r=1;rowCount){ v = col[r]; if( type( v ) == "string" ) v = trim(v); elseif( ..time.istime(v) ) v = ..time.ole(v); result[r][name] = v; } } else { for(r=1;rowCount){ v = col[r]; if( type( v ) == "string" ) v = trim(v); elseif( ..time.istime(v) ) v = ..time.ole(v); result[r] = { [name] = v }; } } } result.fields = fields; return result; } _recordSet = function(rs){ rs[["getTable"]] = function(){ var data = _getRows(rs,false); if(data) return _rows2table(data); }; rs[["stepQuery"]] = function(...){ return rs.getTable(...)[[1]]; }; rs[["nextRecordset"]] = function(){ var rs = rs.NextRecordset(); if(rs)return _recordSet(rs); } return rs; } } /**details(相关范例) 范例程序 / 数据库 / access 范例程序 / 数据库 / excel / SQL 操作 范例程序 / 数据库 / csv / access end details**/ /**intellisense() access = 使用系统自带组件连接 Access 数据库,可支持 Excel 。\n[使用范例](doc://example/Database/access/access.html) access("数据库路径") = 打开数据库连接。\n数据库路径可以指定 mdb,xls等文件格式,\n如果指定的数据库不存在将自动创建数据库文件\n\n如果在其他参数前添加一个 false 参数,则不打开连接,仅返回连接语句。 access("数据库路径",其他连接参数) = @ access("__/*数据库路径(mdb,xls等)*/",{ \n ["Mode"]="Share Deny Read|Share Deny Write"; \n ["Jet OLEDB:Database Password"] = "123456"; \n}) access("数据库连接语句",其他格式化参数) = @access("Provider=Microsoft.Jet.OleDb.4.0;Data Source=%s;Jet OLEDB:Database Password=%s;",\n "/test.db","__/*密码*/" ); 打开数据库连接,\n如果指定的数据库不存在将自动创建数据库文件\n如果存在格式化参数,则调用string.fomat格式化连接串 access() = !access. access.escape(__) = 转义参数指定值为用于 SQL 查询语句的参数化值 access.escapeId(__) = 如果传入参数是文本则转换为 SQL 标识符,\n返回文本首尾会添加中括号,\n\n如果传入参数是表, 则格式化为 SQL 键值对并以 AND 为分隔符,\n如果表中的值为数组,则格式化为 IN 语句 access.format(.(SQL语句,格式化参数->->->) = 格式化 SQL 查询语句。\n所有需要格式化 SQL 语句的函数调用此函数格式化 SQL语句,\n如果格式化参数不是表则调用 string.format 格式化,否则按以下规则格式化:\n\nSQL语句中?或??占位符使用表的数组元素格式化,\n@字符开始的命名参数使用表的名值对元素格式化,\n其中??格式化为标识符,其他占位符格式化为参数值。\n\n字符串转为SQL安全转义字符串,buffer转为 0x4D7953514C 格式,\n数组则自动展开为列表,例如{'a', 'b'}格式化为'a', 'b'\n嵌套数组则格式化为分组列表,例如{{'a', 'b'}, {'c', 'd'}} 格式化为 ('a', 'b'), ('c', 'd')\n非数组的命名表,则格式化为 SQL 键值对,默认以逗号为分隔符,\n??占位符格式化 SQL 键值对则以 AND 为分隔符,并将数组值转换为IN语句 end intellisense**/ /**intellisense(!access) ? = 可直接使用对象的成员获取ADO组件提供的COM常量\n这些常量名的前缀都是 ad dataSourceName = 数据库连接串中指定的ODBC数据源 close() = 关闭数据库连接 getTable(.("select * from [表名]",其他格式化参数) = 返回查询结果集数组\n每个元素代表一行,每行由N个键值对列组成\n返回值的fields成员记录了所有数据列的字段名\n结果集为空也会返回空数组,使用#操作符获取结果集长度 getRows() = 查询并返回包含结果数据的数组\n此函数返回的数据是先列后行,与getTable相反,\n数组由所有列的数据组成,每个列都是由多个行组成的数组\n可以使用 返回数据[ 列号 ][ 行号 ] 获取对应的值,\n也可以使用 数据.字段名[列号] 获取对应的值\n\n返回数组的元表中使用recordCount记录了总行数,\n结果集为空也会返回空数组,可使用 @.recordCount判断记录集的行数\n元表中的fields字段则是记录了所有字段名的数组.\n\n所有值后面的占位空白没有去除\n可使用getTable函数获取处理过空白占位符的数据,\n或参考该函数源码自行处理尾部空白 stepQuery(.("select * from [表名]",其他格式化参数) = 返回查询结果集第一行的数据,由键值对列组成,\n无数据返回null\n\n\n格式化规则请参考 access.format 函数说明,\n格式化参数可以是一个表参数,用于替换SQL中占位符指定的参数,\nSQL语句用中@前缀标明命名参数使用表参数中的名值对格式化,\nSQL语句中的?或??占位符使用表参数中的数组值格式化 openRecordSet(.(sql,游标类型,锁定方法,其他格式化SQL参数) = 打开记录集,游标类型如下:\n0:默认值,启动一个只能向前移动的游标\n1:打开键集类型游标,允许任意移动,并且允许更改记录集\n2:打开动态类型游标,许所有操作,其他用户对记录集的添加、删除、更改在此记录集中\n3:打开原生类型游标\n\n锁定方法如下:\n1:默认值,不能改变数据\n2:悲观锁,编辑时立即锁定数据源的记录\n3:乐观锁,只在调用Update 方法时才锁定记\n4: 乐观批更新 exec(.(sql,其他格式化SQL参数) = 执条SQL语句\n格式化参数规则请参考 access.format 函数说明,\n格式化参数可以是一个表参数,用于替换SQL中占位符指定的参数,\nSQL语句用中@前缀标明命名参数使用表参数中的名值对格式化,\nSQL语句中的?或??占位符使用表参数中的数组值格式化。\n\n执行失败抛出异常。\n执行成功返回受影响的记录行数 createCommand(.(sql,其他格式化SQL参数) = 创建命令对象\n格式化规则请参考 access.format 函数说明,\n格式化参数可以是一个表参数,用于替换SQL中占位符指定的参数,\nSQL语句用中@前缀标明命名参数使用表参数中的名值对格式化,\nSQL语句中的?或??占位符使用表参数中的数组值格式化 existsTable(.("表名") = 判断数据库中是否存在指定表 each(sql,其他格式化参数) = @for(rs in ??.each("select * from [表名]") ){ io.print( rs("字段名").value );__ } each() = !access_rs. openRecordSet() = !access_rs. createCommand() = !access_cmd. connection = 连接对象 connectionString = 打开数据库时指定的连接串\n[数据库连接串写法](https://www.connectionstrings.com/access/) connection.CursorLocation = @.CursorLocation = 3/*adUseClient*/ connection.ConnectionString = 连接串 connection.Errors = 错误集合 connection.Errors.count = 错误数 connection.Errors(.(0) = 参数指定错误索引 connection.Errors() = !ado_conn_err. firstTableName() = 返回数据库的第一个表名。\n参数 @1 可选用一个字符串指定表类型,默认为 "TABLE"。 firstTableObject() = 返回数据库中的第一个表对象。\n参数 @1 可选用一个字符串指定表类型,默认为 "TABLE"。\n!ADOX_Catalog_tbl. findTableObject() = !ADOX_Catalog_tbl. findTableObject(.("表名") = 返回表对象 eachTableObject = @for(tbName,tbType,tbObj in ??.eachTableObject() ){ } eachTableObject() = !ADOX_Catalog_tbl. setPassword(.("新密码","旧密码") = 修改数据库密码,\n如果没有旧密码第二个参数可以不写 beginTrans() = 启动事务,返回嵌套层数\n注意如果未调用此函数开启事务,默认每条独立SQL语句仍然会自动创建独立事务 commitTrans() = 提交事务 rollbackTrans() = 回滚事务 end intellisense**/ /**intellisense(!access_rs) close() = 关闭记录集 eof = 是否移动到记录集尾部,没有更多数据了 bof = 是否已经到记录集开始,没有更多数据了 recordCount = 获取记录总数,\n如果该值为-1,请修改为静态方式打开记录集 move(.(numRecords,start) = 移动游标位置,\n注意第一条记录游标位置为0,\n@start为可选参数,可选使用以下数值:\n _adBookmarkCurrent 0 自当前记录开始\n _adBookmarkFirst 1 自首条记录开始\n _adBookmarkLast 2 自最后一条记录开始 getRows( = 查询并返回包含结果数据的数组\n此函数返回的数据是先列后行,与getTable相反,\n数组由所有列的数据组成,每个列都是由多个行组成的数组\n可以使用 返回数据[ 列号 ][ 行号 ] 获取对应的值 getRows(.(rows,start,fields) = 查询并返回包含结果数据的数组,所有参数可选,\nrows 指定获取行数,默认为-1,即获取所有剩下的行,0,\n@start为可选参数,可选使用以下数值:\n _adBookmarkCurrent 0 自当前记录开始\n _adBookmarkFirst 1 自首条记录开始\n _adBookmarkLast 2 自最后一条记录开始\n@ields 可选用一个字符串、或字符串数组指定要获取的列,\n也可用数值,或数值数组指定要获取的列 getTable() = 返回查询结果集数组\n每个元素代表一行,每行由N个键值对列组成\n返回值的fields成员记录了所有数据列的字段名\n结果集为空也会返回空数组,使用#操作符获取结果集长度 stepQuery() = 返回查询结果集第一行的数据,由键值对列组成\n无数据返回null end intellisense**/ /**intellisense(!access_cmd) commandText = 要执行的SQL命令语句 commandType = 命令类型\n普通SQL为1,存储过程为4 execute(.(ra,parameters.option) = 执行查询,所有参数可选。\n参数ra 返回受查询影响的记录的数目 \n参数parameters 用 SQL 语句传递的参数值 \n参数options 一个或者多个 CommandTypeEnum 或 ExecuteOptionEnum 值 。\n返回记录集对象,execute 返回的记录集没有 getTable,stepQuery 函数。\nexecuteRecords 返回的记录集提供 getTable,stepQuery 函数。 executeStream(.(ra,parameters) = 执行查询返回流,所有参数可选。\n参数ra 返回受查询影响的记录的数目 \n参数parameters 用 SQL 语句传递的参数值 executeNoRecords(.(ra,parameters) = 执行查询不返回记录集,所有参数可选。\n参数ra 返回受查询影响的记录的数目 \n参数parameters 用 SQL 语句传递的参数值 executeRecords(.(ra,parameters.option) = 执行查询,所有参数可选\n参数ra 返回受查询影响的记录的数目 \n参数parameters 用 SQL 语句传递的参数值 \n参数options 一个或者多个 CommandTypeEnum 或 ExecuteOptionEnum 值 。\n返回记录集对象,execute 返回的记录集没有 getTable,stepQuery 函数。\nexecuteRecords 返回的记录集提供 getTable,stepQuery 函数。 cancel() = 取消执行 getTable() = 执行SQL命令返回查询结果集数组\n每个元素代表一行,每行由N个键值对列组成\n返回值的fields成员记录了所有数据列的字段名\n结果集为空也会返回空数组,使用#操作符获取结果集长度 getRows() = 查询并返回包含结果数据的 SafeArray 数组\n此函数返回的数据是先列后行,与 getTable 相反,\n数组由所有列的数据组成,每个列都是由多个行组成的数组\n可以使用 返回数据[ 列号 ][ 行号 ] 获取对应的值,\n也可以使用 数据.字段名[列号] 获取对应的值\n\n返回数组的元表中使用recordCount记录了总行数,\n结果集为空也会返回空数组,可使用 @.recordCount判断记录集的行数\n元表中的fields字段则是记录了所有字段名的数组.\n\n所有值后面的占位空白没有去除\n可使用getTable函数获取处理过空白占位符的数据,\n或参考该函数源码自行处理尾部空白 stepQuery() = 执行SQL命令\n返回查询结果集第一行的数据,由键值对列组成\n无数据返回null each() = @for(rs in ??.each() ){ io.print( rs(0).value );__/*执行SQL命令并遍历结果集*/ } createParameter(.(名字,字段类型,参数类型,字段大小,参数值) = 创建参数\n参数中用到的常量请使用COM对象的成员常量获取,\n例如cmd.adLongVarWChar\n这个函数创建的参数还需要调用parameters.append添加到执行参数中\n\n不建议直接调用此函数,可以使用更简单的addParameter或bind函数添加参数 parameters = 参数列表 parameters.append(.(参数对象) = 添加参数\n注意access的参数对象虽然必须设置正确的名字,\n但实际上他只按添加顺序执行 parameters.count() = 返回参数长度 parameters.delete(.(索引) = 删除参数 parameters.refresh() = 刷新参数 parameters("__/*参数名*/") = 返回已添加的参数 bind(__) = 参数是一个表,\n可使用多个键值对批量指定SQL命令对象的多个参数,\n此函数会按参数在SQL中出现的顺序逐个添加参数,\nSQL语句中所有参数必须使用@前缀命名,\n此函数返回命令对象自身 addParameter( = 调用createParameter创建参数对象,\n设置值并添加到SQL执行参数中\n注意access的参数对象虽然必须设置正确的名字,\n但实际上他只按添加顺序执行 addParameter(.(名字,值,参数类型,字段类型,字段大小) = 直接添加SQL执行参数\n除名字,值以外的其他参数不必要设置\n返回创建的参数对象\n\n\n注意access的参数对象虽然必须设置正确的名字,\n但实际上他只按添加顺序执行 bind() = !access_cmd. addParameter() = !access_parameter. end intellisense**/ /**intellisense(!access_parameter) value = 参数值 direction = 参数的类型,默认是adParamInput name = 参数名称 size = 数据长度 end intellisense**/ /**intellisense(!ado_conn_err) Description = 错误描述 Number = 错误代码 Source = 错误对象 SQLState = 数据源 NativeError = 数据源错误代码 end intellisense**/ /**intellisense(!ADOX_Catalog_tbl) Name = 表名 Type = 表示表类型的字符串。\n例如 "TABLE", "SYSTEM TABLE", 或 "GLOBAL TEMPORARY" Keys = 键集合 Indexes = 索引集合 Columns = 列集合 Columns.Count = 总数 Columns(.("列名") = 参数也可以写数值索引 Columns() = !ADOX_Catalog_column. end intellisense**/ /**intellisense(!ADOX_Catalog_column) Name = 列名 Type = 类型 DefinedSize = 字段大小 end intellisense**/ /**intellisense() _adBookmarkCurrent=@0/*_adBookmarkCurrent*/ _adBookmarkFirst=@1/*_adBookmarkFirst*/ _adBookmarkLast=@2/*_adBookmarkLast*/ _adOpenDynamic=@2/*_adOpenDynamic*/ _adOpenForwardOnly=@0/*_adOpenForwardOnly*/ _adOpenKeyset=@1/*_adOpenKeyset*/ _adOpenStatic=@3/*_adOpenStatic*/ _adOpenUnspecified=@-1/*_adOpenUnspecified*/ end intellisense**/