积极答复者
PHP访问SQL Server 2005 的一个神奇错误,查询出的资料不对

问题
-
环境:linux 下 通过 freeTDS 访问 sql server 2005
异常现象为不确定什么时候会 查询结果错误.
最初我是通过 select * from tb 查询,发现漏了几条记录,后来发现用 select count(*) from tb 发现通过 php去查询就是会少掉这几笔.
于是我加了条件缩小查询范围,结果发现少掉的记录是固定的,这些记录通过php去查询时就是隐形的.
不死心的我在命令行下直接使用 tsql 查询,结果却又是正常的.
接下来,我通过 SQL Server Profiler 去trace,发现sql server 接收到sql 语句是没有问题的,同样的语句,得到不同的结果.
因为我担心是不是数据在传输过程中产生的错误,我直接将查询结果写到另一个表里,按道理来说这样应该能得到相同的结果.
但最神奇的事情发生了,就算数据不出sql server ,通过php送来的sql 查询就是看不到那些记录.
insert into temptb(rows,writetime) select count(*) ,getdate() from ym_employees_wechat_all where empno like 'y1503%'
说明:
1. 查询的这个表中的数据是不变的
2. 不是每个表都会有这种问题
3.同一个表中的数据复制到其它数据库中可以正常查询
那么,那位大神来帮忙分析分析,问题到底出在哪?
答案
-
正好没事,就仔细看了你发的trc文件。问题找到了,默认的配置项不一样,导致查询结果差异。测试SQL如下:
set concat_null_yields_null on SELECT count(*) FROM [dbo].[tb001_view] set concat_null_yields_null off SELECT count(*) FROM [dbo].[tb001_view] --返回结果 ----------- 13 (1 行受影响) ----------- 10 (1 行受影响)
family as water
- 已标记为答案 老施 2017年9月28日 5:49
全部回复
-
上周杂事较多,先找到替代方法后就没再管了,今天抽空把资料简洁一下,再放上来.
一个table,先写了个view,然后再写个view查前面的view,用于条件判断.
因为原来写view的早就不在了,所以也不知道为什么要这样写.
tb001:
empno,COMPANY_CODE,EMAIL,MOBILE_PHONE
Y15036,02,Y15036@domain.com,
Y05043,02,Y05043@domain.com,
Y11055,02,Y11055@domain.com,
Y11104,02,Y11104@domain.com,99Y11104
Y02131,02,Y02131@domain.com,99Y02131
Y04001,02,Y04001@domain.com,99Y04001
Y04061,02,Y04061@domain.com,99Y04061
Y05039,02,Y05039@domain.com,99Y05039
Y05110,02,Y05110@domain.com,99Y05110
Y13029,02,Y13029@domain.com,99Y13029
Y13008,02,Y13008@domain.com,99Y13008
Y13043,02,Y13043@domain.com,99Y13043
Y13052,02,Y13052@domain.com,99Y13052view1:
ALTER VIEW [dbo].[tb001_view_New] AS SELECT EMPNO, MOBILE_PHONE_HR, EMAIL, COMPANY_CODE, CASE WHEN company_code = 02 THEN '+886' + substring(replace(MOBILE_PHONE_HR, '-', ''), 2, 9) ELSE MOBILE_PHONE_HR END AS MOBILE_PHONE FROM (SELECT EMPNO, [COMPANY_CODE], CASE WHEN MOBILE_PHONE = '' THEN NULL ELSE MOBILE_PHONE END AS MOBILE_PHONE_HR, CASE WHEN EMAIL = 'admin@domain.com' THEN NULL ELSE EMAIL END AS EMAIL FROM dbo.tb001 ) AS t WHERE (MOBILE_PHONE_HR IS NOT NULL) OR (EMAIL IS NOT NULL)
view2:
ALTER VIEW [dbo].[tb001_view] AS SELECT EMPNO, MOBILE_PHONE FROM dbo.tb001_view_New WHERE (EMPNO NOT IN (SELECT EMPNO FROM tb001_view_new AS tb001_view_new_4 WHERE (MOBILE_PHONE IN (SELECT MOBILE_PHONE FROM dbo.tb001_view_new AS tb001_view_new_3 WHERE (MOBILE_PHONE IS NOT NULL) GROUP BY MOBILE_PHONE HAVING (COUNT(1) > 1))) UNION SELECT EMPNO FROM dbo.tb001_view_new AS tb001_view_new_2 WHERE (EMAIL IN (SELECT EMAIL FROM dbo.tb001_view_new AS tb001_view_new_1 WHERE (EMAIL IS NOT NULL) GROUP BY EMAIL HAVING (COUNT(1) > 1)))))
除了PHP中, SELECT count(*) FROM [bonne].[dbo].[tb001_view] 会得到全部13笔
在PHP中, SELECT count(*) FROM [bonne].[dbo].[tb001_view] 只会得到MOBILE_PHONE不为空的10笔.
<?PHP $con=mssql_connect("c10133013","sa","Ab-123456"); $db=mssql_select_db("bonne",$con); $query = " select count(*) from tb001_view "; $results= mssql_query($query); while ($row = mssql_fetch_array($results)){ echo '->'.$row[0].PHP_EOL; } [root@ksyoweb01 tmp]# php tt.php ->10
大神来帮忙解惑了~~
-
查询view时,连用tsql 命令行执行也会得到错误结果,直接查询table还是一样都正确的.
Hi 老施,
事实上,确实是sql server提供访问端口,client提交的query都是在sql server中执行的,然后返回结果给client。
而且我们拿了几台机子测试了你的query,都没法重现这个问题,你可以尝试升级一下SQL Server和驱动。
Best Regards,
Teige
MSDN Community Support<br/> Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact <a href="mailto:MSDNFSF@microsoft.com">MSDNFSF@microsoft.com</a>.
- 已编辑 Teige GaoModerator 2017年9月22日 7:24
-
Hello,Teige!
我不知道你的运行环境是不是在Linux下,所以没法重现这个问题.
我这边使用了两台linux安装有不同版本的php freetds 连接 不同版本的 sql server 都会有同样问题.
SQL SERVER试过两个2015 Ent和2014 Express
ClientA: CentOS5+PHP 5.2.17+FreeTDS 0.64
ClientB:CentOS7+PHP 5.4.16+FreeTDS 0.95.81
freetds.conf 中使用的tds version 为8.0
为了确保不是偶然现象,我新建了db,并重新试了一下,结果还是一如之前所述.
这里没法上传附件,所以我把测试的tabel和view打包了放在下面
链接:pan.baidu.com/s/1o8jz7se 密码:0a7n
最后,如果真的query只在内部执行,那就解释不了了..
对应的截图和trace也那上面了.
-
正好没事,就仔细看了你发的trc文件。问题找到了,默认的配置项不一样,导致查询结果差异。测试SQL如下:
set concat_null_yields_null on SELECT count(*) FROM [dbo].[tb001_view] set concat_null_yields_null off SELECT count(*) FROM [dbo].[tb001_view] --返回结果 ----------- 13 (1 行受影响) ----------- 10 (1 行受影响)
family as water
- 已标记为答案 老施 2017年9月28日 5:49
-
正好没事,就仔细看了你发的trc文件。问题找到了,默认的配置项不一样,导致查询结果差异。测试SQL如下:
set concat_null_yields_null on SELECT count(*) FROM [dbo].[tb001_view] set concat_null_yields_null off SELECT count(*) FROM [dbo].[tb001_view] --返回结果 ----------- 13 (1 行受影响) ----------- 10 (1 行受影响)
family as water
非常感谢, 这就是功力的体现.
老司机才知道因为空的原因导致查询结果不正确那就要从跟这个有关的地方入手..