FoxPro的一条把柄!(根据我的研究,在Delphi中也有此问题)解决之道是:把长长的语句先放在一个变量中,再将此变量作为参数赋给SQLEXEC()函数。
关于分隔符的使用技巧,Visual FoxPro中分隔字符串使用三种符号:双引号、单引号、方括号。在配置要传送的语句时一定要用双引号作为字符串的分隔符,其他的两个符号应另作他用。
以上的建议绝对经典,以下我们就用实例来说明:
在SQL Server中要得到详细销售情况的SQL-Select语句如下(详细的知识见本人撰写的《SELECT-SQL 周周谈》一文):
SELECT
ORDERS.SHIPNAME,ORDERS.SHIPADDRESS,ORDERS.SHIPCITY,ORDERS.SHIPREGION,ORDERS.SHIPPOSTALCODE, ORDERS.SHIPCOUNTRY,ORDERS.CUSTOMERID,CUSTOMERS.COMPANYNAME CUSTOMERNAM,
EMPLOYEES.FIRSTNAME+' '+EMPLOYEES.LASTNAME AS SALESPERSON, ORDERS.ORDERID,ORDERS.ORDERDATE,ORDERS.REQUIREDDATE, ORDERS.SHIPPEDDATE,SHIPPERS.COMPANYNAME AS SHIPPERNAME, [ORDER
DETAILS].PRODUCTID,PRODUCTS.PRODUCTNAME,[ORDER
DETAILS].UNITPRICE,[ORDER DETAILS].QUANTITY,[ORDER DETAILS].DISCOUNT, [ORDER DETAILS].UNITPRICE*[ORDER DETAILS].QUANTITY*(1-[ORDER DETAILS].DISCOUNT) AS EXTENDEDPRICE, ORDERS.FREIGHT FROM ((((EMPLOYEES INNER JOIN ORDERS ON EMPLOYEES.EMPLOYEEID=ORDERS.EMPLOYEEID)
INNER JOIN CUSTOMERS ON ORDERS.CUSTOMERID=CUSTOMERS.CUSTOMERID) INNER JOIN SHIPPERS ON ORDERS.SHIPVIA=SHIPPERS.SHIPPERID)
INNER JOIN [ORDER DETAILS] ON ORDERS.ORDERID=[ORDER DETAILS].ORDERID) INNER JOIN PRODUCTS ON [ORDER DETAILS].PRODUCTID=PRODUCTS.PRODUCTID
这是一句12行,不计空格864个字符的大型语句,现在要通过Visual FoxPro的SQLEXEC()函数传送:
local csq
&&配置待传送的语句 csql=csql+\
ORDERS.SHIPNAME,ORDERS.SHIPADDRESS,ORDERS.SHIPCITY,ORDERS.SHIPREGION,\
csql=csql+\,ORDERS.CUSTOMERID,\
csql=csql+\csql=csql+\'+EMPLOYEES.LASTNAME SALESPERSON,ORDERS.ORDERID,ORDERS.ORDERDATE,\
AS AS
csql=csql+\TE,ORDERS.SHIPPEDDATE,SHIPPERS.COMPANYNAME AS SHIPPERNAME,\csql=csql+\DETAILS].PRODUCTID,PRODUCTS.PRODUCTNAME,[ORDER DETAILS].UNITPRICE,\
csql=csql+\,[ORDER DETAILS].DISCOUNT,\csql=csql+\DETAILS].UNITPRICE*[ORDER DETAILS].QUANTITY*(1-[ORDER DETAILS].DISCOUNT) AS EXTENDEDPRICE,\csql=csql+\csql=csql+\FROM ((((EMPLOYEES
INNER
JOIN
ORDERS
ON ON
EMPLOYEES.EMPLOYEEID=ORDERS.EMPLOYEEID)\csql=csql+\INNER JOIN
ORDERS.CUSTOMERID=CUSTOMERS.CUSTOMERID)\
CUSTOMERS
csql=csql+\
csql=csql+\INNER JOIN [ORDER DETAILS] ON ORDERS.ORDERID=[ORDER DETAILS].ORDERID)\csql=csql+\INNER
JOIN
PRODUCTS
ON
[ORDER
DETAILS].PRODUCTID=PRODUCTS.PRODUCTID\&&传送,得到的光标名称为默认的SqlResult SQLEXEC(hconn,csql)
解释:由于语句很长,我花费了多条赋值语句才完成配置这个字符串。大家注意到了我选用双引号作为字符串分隔符,这里面是有大学问的。在SQL Server中有待空格的表名如:Order Details,当它用于SQL语句时,就必须要用方括号标示,所以如果在Visual FoxPro中如果用方括号分割字符串的话,就会有冲突!;单引号是SQL Server中分隔字符串、日期值的符号,在Visual FoxPro中如果使用单引号分隔字符串的话,也会造成冲突,当然在以上语句中我们没有看到单引号的身影,不过我们做一个变动,大家就会感到问题的存在了!
local csq
&&配置待传送的语句 csql=csql+\
ORDERS.SHIPNAME,ORDERS.SHIPADDRESS,ORDERS.SHIPCITY,ORDERS.SHIPREGION,\
csql=csql+\,ORDERS.CUSTOMERID,\
csql=csql+\csql=csql+\'+EMPLOYEES.LASTNAME SALESPERSON,ORDERS.ORDERID,ORDERS.ORDERDATE,\
csql=csql+\TE,ORDERS.SHIPPEDDATE,SHIPPERS.COMPANYNAME AS SHIPPERNAME,\csql=csql+\DETAILS].UNITPRICE,\
csql=csql+\,[ORDER DETAILS].DISCOUNT,\
csql=csql+\DETAILS].UNITPRICE*[ORDER DETAILS].QUANTITY*(1-[ORDER DETAILS].DISCOUNT) AS EXTENDEDPRICE,\
DETAILS].PRODUCTID,PRODUCTS.PRODUCTNAME,[ORDER
AS
csql=csql+\
csql=csql+\FROM ((((EMPLOYEES INNER EMPLOYEES.EMPLOYEEID=ORDERS.EMPLOYEEID)\csql=csql+\INNER JOIN
ORDERS.CUSTOMERID=CUSTOMERS.CUSTOMERID)\
JOIN
ORDERS
ON ON
CUSTOMERS
csql=csql+\csql=csql+\INNER JOIN [ORDER DETAILS] ON ORDERS.ORDERID=[ORDER DETAILS].ORDERID)\csql=csql+\INNER
JOIN
PRODUCTS
ON
[ORDER
DETAILS].PRODUCTID=PRODUCTS.PRODUCTID\
csql=csql+\TE BETWEEN '1996-10-01' AND '1997-09-30'\csql=csql+\csql=csql+\&&传送,得到的光标名称为默认的SqlResult SQLEXEC(hconn,csql)
传递变量
上面一个例子充分证明了我关于字符串分隔符的经验,接着我又为大家提出了一个新课题:怎样传递变量到SQL Server中。上例中,我们为语句加入了Where字句,下面我们把其中的条件值变为变量,这样这句SQL传递才变得真正的有意义!
我以为关于变量的传递有两种方法,下面逐一介绍。
第一种是利用:问号+变量来传递的,这是一种常用的方法,用起来也很简单,不用担心变量的类型,ODBC会自动的转化。下面的例子中就涉及到了日期型、数值型、字符型变量,我们根本不用担心变量类型的转化,只要在前面加上问号填入语句中就行了:
local csq
&&要传送的变量 dDate1={^1996-10-01} dDate2={^1997-09-30} cCustomerID=\nQty=50
&&配置待传送的语句 csql=csql+\
ORDERS.SHIPNAME,ORDERS.SHIPADDRESS,ORDERS.SHIPCITY,ORDERS.SHIPREGION,\
csql=csql+\,ORDERS.CUSTOMERID,\
csql=csql+\
csql=csql+\'+EMPLOYEES.LASTNAME AS SALESPERSON,ORDERS.ORDERID,ORDERS.ORDERDATE,\csql=csql+\TE,ORDERS.SHIPPEDDATE,SHIPPERS.COMPANYNA
ME AS SHIPPERNAME,\
csql=csql+\DETAILS].PRODUCTID,PRODUCTS.PRODUCTNAME,[ORDER DETAILS].UNITPRICE,\
csql=csql+\,[ORDER DETAILS].DISCOUNT,\
csql=csql+\DETAILS].UNITPRICE*[ORDER DETAILS].QUANTITY*(1-[ORDER DETAILS].DISCOUNT) AS EXTENDEDPRICE,\csql=csql+\
csql=csql+\FROM ((((EMPLOYEES INNER EMPLOYEES.EMPLOYEEID=ORDERS.EMPLOYEEID)\csql=csql+\
INNER
JOIN
JOIN
ORDERS
ON ON
CUSTOMERS
ORDERS.CUSTOMERID=CUSTOMERS.CUSTOMERID)\
csql=csql+\csql=csql+\INNER JOIN [ORDER DETAILS] ON ORDERS.ORDERID=[ORDER DETAILS].ORDERID)\
csql=csql+\INNER JOIN PRODUCTS DETAILS].PRODUCTID=PRODUCTS.PRODUCTID\
ON
[ORDER
csql=csql+\TE BETWEEN ?dDate1 AND ?dDate2\csql=csql+\csql=csql+\&&传送,得到的光标名称为默认的SqlResult SQLEXEC(hconn,csql)
分析:我们先来看一看书写的规范,请看:
csql=csql+\TE BETWEEN ?dDate1 AND ?dDate2\csql=csql+\csql=csql+\
问号+变量作为参数放置在SQL语句中,你也许会奇怪:问号+变量怎么还要放在Visual FoxPro的双引号里面,这不是作为一个字符串了吗?我们首先要清楚Visual FoxPro的SQLEXEC()传递的只能是一个字符串,所以问号+变量应当作为字符串的一部分!SQLEXEC()会将这个字符串给ODBC,ODBC分析一下这个字符串,他会发现问号+变量的特殊写法,于是它传递给SQL Server的语句是(整句太长,我就选择最后一段):
WHERE ORDERS.ORDERDATE BETWEEN @P1 AND @P2 AND ORDERS.CUSTOMERID LIKE @P3 AND [ORDER DETAILS].QUANTITY>@P4 ', N'@P1 datetime,@P2 datetime,@P3 varchar(3),@P4 float', 'Oct 1 1996 12:00AM', 'Sep 30 1997 12:00AM', '%C%', 5.000000000000000e+001
看到没有,所有变量都被重新命名,并用SQL Server的写法规范!
第二种方法是利用Visual FoxPro把变量合并到语句中去,产生一个字符串,这样的话传递给SQL Server的语句就是一个完整的字符串,其中不带变量,这样做的好处是更有效率,因为ODBC不用处理变量的传递,SQL Server也不用处理变量信息了。