不同环境中 SQL_SRV 行为的差异

问题描述 投票:0回答:1

我在远程计算机上有一个 PHP 脚本,它从 Microsoft SQL Server 数据库中提取数据并将数据插入到 MySQL 数据库中。我设置了一个 cron 作业来每小时运行该脚本,以便 MySQL 数据库与 SQL Server 数据库保持同步。

我的问题是,每当我在远程计算机上运行脚本时,对 SQL Server 的查询结果都是不完整的,并且在给定相同参数时会有所不同。无论我从命令行还是使用 cronjob 运行它,它都不会检索正确的行数。

但是,如果我在不同的环境(在 SQL Server Management Studio 中或本地测试脚本中)运行查询,结果始终是正确的。

我的第一个想法是这是一个环境配置问题,但我发现使用

init_set()
函数将
max_execution_time
设置为 0,
max_input_time
设置为 0,
memory_limit
设置为 -1(根据 php.ini 文件)。 ini 指令文档)对查询结果没有影响。

我的第二个想法是,这可能是远程计算机上的防火墙或网络设置的问题,但计算机上没有直接安装防火墙,并且虽然网络设置对入站连接极为严格,但出站连接却完全开放。

我在网上看到了一些类似的问题 -

(1)(2)(3)(4) - 但由于具体情况,解决方案要么不起作用,要么不适用我正在运行的查询与他们正在运行的查询的比较。

我不确定还有什么问题。

本地测试脚本如下:

<?php $connection_info = array( "UID"=>"UserID", "PWD"=>"password", "Database"=>"database_name" ); $serverName = 'database_host'; try{ $conn = sqlsrv_connect($serverName, $connection_info); } catch(Exception $e){ die("Not able to connect."); } echo "Connected!\n"; $sql = " SELECT SP.SaleInvoiceID, SP.AssociationNumber, SP.Priority, S.Abbreviation, GP.GlobalProductID, SI.OrderEntryID, SI.OriginalSaleInvoiceID, SI.AccountsReceivableID, SI.EmployeeID3, SI.InvoiceIDByStore AS [invoice], (C.Customer_Name + ' ' + C.First_Name + ' ' + C.Last_Name) AS [customer], C.Id_Number as [customer_id], GP.ProductIdentifier AS [product_sku], RGP.ManufacturerPartNumber AS [model], CAST( L2.FieldText AS varchar ) AS [manufacturer], CAST( L1.FieldText AS varchar ) AS [description], CAST( L3.FieldText AS varchar ) AS [category], SP.Quantity AS Qty, SP.SerialNumber, SP.ContractNumber, SP.MobileNumber, GP.CategoryNumber, SP.UnitPrice, SP.UnitCost, SP.ListPrice, SI.SplitRate1, SI.SplitRate2, SI.EmployeeID1, SI.EmployeeID2, E1.Employee_Name AS [Employee1], E2.Employee_Name AS [Employee2], SI.DateCreated, SI.Comments FROM [database_name].[dbo].[SaleInvoices] SI INNER JOIN [database_name].[dbo].[SaleInvoicesAndProducts] SP ON SI.SaleInvoiceID = SP.SaleInvoiceID INNER JOIN [database_name].[dbo].[iQclerk_GlobalProducts] GP ON SP.GlobalProductID = GP.GlobalProductID INNER JOIN [database_name].[dbo].[LanguageTranslations] L1 ON GP.ProductNameID = L1.ReferenceID INNER JOIN [database_name].[dbo].[Stores] S ON S.StoreID = SI.StoreID1 INNER JOIN [database_name].[dbo].[Customer_Information] C ON SI.CustomerID1 = C.Id_Number INNER JOIN [database_name].[dbo].[Employees] E1 ON E1.Id_Number = SI.EmployeeID1 INNER JOIN [database_name].[dbo].[Categories] CAT ON CAT.CategoryNumber = GP.CategoryNumber INNER JOIN [database_name].[dbo].[LanguageTranslations] L3 ON CAT.CategoryPathID = L3.ReferenceID LEFT OUTER JOIN [database_name].[dbo].[Employees] E2 ON E2.Id_Number = SI.EmployeeID2 LEFT OUTER JOIN [database_name].[dbo].[RegularGlobalProducts] RGP ON RGP.GlobalProductID = GP.GlobalProductID LEFT OUTER JOIN [database_name].[dbo].[Manufacturers] M ON M.ManufacturerID = RGP.ManufacturerID LEFT OUTER JOIN [database_name].[dbo].[LanguageTranslations] L2 ON M.ManufacturerNameID = L2.ReferenceID WHERE SI.DateCreated BETWEEN cast( '2024-03-04 00:00:00' AS DateTime ) AND cast( '2024-05-09 23:59:59' AS DateTime ) AND L3.LanguageCode = 'en-us' "; $result = sqlsrv_query($conn, $sql, array(), array("Scrollable" => 'static')); print("Data package received, etrieving data from package...\n"); $result_rows = array(); $i = 1; while( $row = sqlsrv_fetch_array( $result, SQLSRV_FETCH_ASSOC ) ){ print("Records retrieved: ".$i."\r"); $i++; array_push($result_rows, $row); } print("\n"); print(sizeof($result_rows));
数据流在远程机器上更加分离:

<?php class SQLSRV{ protected $dbConn; public function open_db($server, $user, $password, $database, $throwError=false) { global $_REGISTRY; ini_set("max_execution_time","0"); ini_set("max_input_time","0"); ini_set("memory_limit","-1" ); $errorMsg = "SQLSRV_ERROR: Cannot connect to SQL server database!\n"; $serverName = $server; $connectionInfo = array( 'UID' => $user, 'PWD' => $password, 'DATABASE' => $database ); $this->dbConn = sqlsrv_connect($serverName, $connectionInfo); if (!$this->dbConn) { $_REGISTRY['STATE'] = 'FATAL'; $_REGISTRY['ERROR_MESSAGE'] = 'DATABASE_CONNNECTION_ERROR'; if($throwError) throw new \ErrorException( $errorMsg, 10001, 0,__file__, __line__ ); else return $errorMsg; } return true; } public function query( $sql, $throwError=true ) { if( !$sql ) return null; if(!$throwError) { sqlsrv_configure("WarningReturnAsErrors", 0); } $errorMsg = "SQLSRV_ERROR: No database connection"; if(!$this->dbConn ) { if( $throwError) throw new \ErrorException( $errorMsg, 10001, 0,__file__, __line__ ); else return $errorMsg; } $query = false; try { $query = sqlsrv_query( $this->dbConn, $sql, array(), array("Scrollable" => 'static') ); } catch( Exception $e ) {} $queryError = 'SQLSRV_ERROR: ' . sqlsrv_errors() . "\n\n<pre>$sql</pre>\n"; if(!$throwError) { sqlsrv_configure("WarningReturnAsErrors", 1); } if (!$query) { if($throwError) throw new \Exception( $queryError ); else return $queryError; } else { return $query; } } public function fetchData( $sql, $throwError=true ) { $res = $this->query( $sql, $throwError ); if($res) { $queryError = 'SQLSRV_ERROR: ' . sqlsrv_errors() . "\n\n$sql\n"; file_put_contents('/var/tmp/sqlsrv.log', "fetchData Res: $queryError\n", FILE_APPEND ); try{ if(sqlsrv_num_rows($res)) { $ar = array(); while( $row = sqlsrv_fetch_array( $res, SQLSRV_FETCH_ASSOC ) ) { array_push($ar, $row); } return $ar; } } catch( \Exception $e ) { return false;} } else return false; } } $sql_srv_obj = new SQLSRV(); $sql_srv_obj->open_db('database_host', 'username', 'password', 'database_name'); $sql_query = " SELECT SP.SaleInvoiceID, SP.AssociationNumber, SP.Priority, S.Abbreviation, GP.GlobalProductID, SI.OrderEntryID, SI.OriginalSaleInvoiceID, SI.AccountsReceivableID, SI.EmployeeID3, SI.InvoiceIDByStore AS [invoice], (C.Customer_Name + ' ' + C.First_Name + ' ' + C.Last_Name) AS [customer], C.Id_Number as [customer_id], GP.ProductIdentifier AS [product_sku], RGP.ManufacturerPartNumber AS [model], CAST( L2.FieldText AS varchar ) AS [manufacturer], CAST( L1.FieldText AS varchar ) AS [description], CAST( L3.FieldText AS varchar ) AS [category], SP.Quantity AS Qty, SP.SerialNumber, SP.ContractNumber, SP.MobileNumber, GP.CategoryNumber, SP.UnitPrice, SP.UnitCost, SP.ListPrice, SI.SplitRate1, SI.SplitRate2, SI.EmployeeID1, SI.EmployeeID2, E1.Employee_Name AS [Employee1], E2.Employee_Name AS [Employee2], SI.DateCreated, SI.Comments FROM [database_name].[dbo].[SaleInvoices] SI INNER JOIN [database_name].[dbo].[SaleInvoicesAndProducts] SP ON SI.SaleInvoiceID = SP.SaleInvoiceID INNER JOIN [database_name].[dbo].[iQclerk_GlobalProducts] GP ON SP.GlobalProductID = GP.GlobalProductID INNER JOIN [database_name].[dbo].[LanguageTranslations] L1 ON GP.ProductNameID = L1.ReferenceID INNER JOIN [database_name].[dbo].[Stores] S ON S.StoreID = SI.StoreID1 INNER JOIN [database_name].[dbo].[Customer_Information] C ON SI.CustomerID1 = C.Id_Number INNER JOIN [database_name].[dbo].[Employees] E1 ON E1.Id_Number = SI.EmployeeID1 INNER JOIN [database_name].[dbo].[Categories] CAT ON CAT.CategoryNumber = GP.CategoryNumber INNER JOIN [database_name].[dbo].[LanguageTranslations] L3 ON CAT.CategoryPathID = L3.ReferenceID LEFT OUTER JOIN [database_name].[dbo].[Employees] E2 ON E2.Id_Number = SI.EmployeeID2 LEFT OUTER JOIN [database_name].[dbo].[RegularGlobalProducts] RGP ON RGP.GlobalProductID = GP.GlobalProductID LEFT OUTER JOIN [database_name].[dbo].[Manufacturers] M ON M.ManufacturerID = RGP.ManufacturerID LEFT OUTER JOIN [database_name].[dbo].[LanguageTranslations] L2 ON M.ManufacturerNameID = L2.ReferenceID WHERE SI.DateCreated BETWEEN cast( '2024-03-04 00:00:00' AS DateTime ) AND cast( '2024-05-09 23:59:59' AS DateTime ) AND L3.LanguageCode = 'en-us' "; $data = $sql_srv_obj->fetchData($sql_query);
所有查询方式的登录信息都是相同的。

php sql-server apache
1个回答
0
投票
问题出在我定义光标类型的方式上:

//Old format $result = sqlsrv_query($conn, $sql, array(), array("Scrollable" => 'static')); //New new format $result = sqlsrv_query($conn, $sql, array(), array("Scrollable" => SQLSRV_CURSOR_STATIC));
虽然旧格式在我的本地计算机上有效,但它不是传递到 

sqlsrv_query()

 函数的有效值。 SQLSRV_CURSOR_STATIC 是在 SQLSRV 包中定义的常量。

© www.soinside.com 2019 - 2024. All rights reserved.