使用 PHP 通过 ODBC 运行 MSSQL 存储过程(并获取结果)

发布于 2024-09-26 06:04:41 字数 1368 浏览 2 评论 0原文

我的工作是将所有 PHP Web 应用程序从 Windows 生产 Web 服务器转移到专门用于 PHP 应用程序的新 Linux 服务器环境。棘手的部分是,我们运行的几个 PHP 应用程序正在使用 MSSQL 数据库,因此必须重写所有数据库连接才能使用 unixODBC/FreeTDS,因为 Linux 上的 PHP 不支持 mssql_connect() 并且它是相关的功能。

我已经关闭了连接并且基本查询执行得很好。我遇到的问题是运行存储过程以及通过 ODBC 复制 mssql_init()/mssql_bind()/mssql_execute() 功能。

我正在研究的问题领域如下:

$sp = mssql_init('sp_Search', $this->_link);
mssql_bind($sp, '@search', $this->_searchString, SQLVARCHAR);
$results = mssql_execute($sp);

我已经阅读了大量有关各种 ODBC 函数和 MSSQL 函数的文章。我尝试使用 odbc_prepare()/odbc_execute() 函数,但无济于事(我总是从 SQL 服务器收到 HY000 错误代码)。我最接近的是:

$results = odbc_exec($this->_link, "EXEC sp_Search @search='@this->_searchString'");

通过 MSSQL 管理控制台运行该查询(“EXEC sp_Search @search='blah'”)工作完美,但通过 PHP 它似乎工作,但如果我尝试从结果集时,我收到“此结果索引处没有可用的元组”错误。无论如何,odbc_next_result() 都会返回 false。

我还尝试将光标设置在与 SQL_CUR_USE_ODBC 的连接上,但这也没有帮助。有人有这样做的经验吗?是否有可能,或者如果没有本机 MSSQL 驱动程序,该功能根本不可用?

编辑:

为了澄清,我尝试使用 odbc_prepare() 和 odbc_execute() 如下:

$results = odbc_prepare($this->_link, "{CALL sp_Search(?)}");
$params = array($this->_searchString);
odbc_execute($results, $params);

这会导致以下错误:

Warning: odbc_execute(): SQL error: Failed to fetch error message, SQL state HY000 in SQLExecute

My work is in the process of moving all of our PHP web applications off of our Windows production web server to a new Linux server environment specifically for PHP apps. The sticky part is, several of the PHP applications we're running are using MSSQL databases, and therefore all the DB connectivity has to be re-written to use unixODBC/FreeTDS since PHP on Linux doesn't support mssql_connect() and it's related functions.

I've gotten the connectivity down and basic queries execute fine. The problem I'm having is with running stored procedures, and replicating the mssql_init()/mssql_bind()/mssql_execute() functionality via ODBC.

The problem area I'm working on is the following:

$sp = mssql_init('sp_Search', $this->_link);
mssql_bind($sp, '@search', $this->_searchString, SQLVARCHAR);
$results = mssql_execute($sp);

I've read a bunch about the various ODBC functions and MSSQL functions. I've tried using the odbc_prepare()/odbc_execute() functions, to no avail (I always receive HY000 error codes from the SQL server). The closest I've come is this:

$results = odbc_exec($this->_link, "EXEC sp_Search @search='@this->_searchString'");

Running that query ("EXEC sp_Search @search='blah'") via the MSSQL Management Console works perfectly, but via PHP it seems to work, but if I try to fetch the rows from the result set, I get "No tuples available at this result index" errors. And odbc_next_result() returns false no matter what.

I also tried setting the cursor on the connection to SQL_CUR_USE_ODBC but that didn't help either. Does anybody have any experience doing this? Is it even possible, or is that functionality simply not available without the native MSSQL driver?

Edit:

Just to clarify, I have tried using odbc_prepare() and odbc_execute() as follows:

$results = odbc_prepare($this->_link, "{CALL sp_Search(?)}");
$params = array($this->_searchString);
odbc_execute($results, $params);

This results in the following error:

Warning: odbc_execute(): SQL error: Failed to fetch error message, SQL state HY000 in SQLExecute

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

澉约 2024-10-03 06:04:41

这是一种利用 PDO 的面向对象方法,该方法更安全一些。

请注意,此处的语法适用于 SQL Server 2012。主要区别在于您的 SQL 语句(您不需要将 ? 括起来,并且使用 EXEC 而不是 CALL)。

另外,在这个例子中,$dbconn对象假设你有一个正确配置的odbc.ini文件和有效的ODBC配置(这可能很棘手,具体取决于你的发行版......对于这个例子中的工作代码,我在后面设置了FreeTDS一切都在 CentOS 机器上,请参阅 https://serverfault.com/a/622088 了解更多信息。

$dbconn = new PDO("odbc:YOUR_DB", "YOUR_USER", "YOUR_PASS");

  // Set up some useful error reporting.
  $dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    $sql = "EXEC [data_mart].[dbo].[your_stored_procedure] ?,?,?";
    $stmt = $dbconn->prepare($sql);
    $id = 1;
    $start_date = "2015-08-01"
    $end_date = "2015-08-02";
    $stmt->bindParam(1, $id);
    $stmt->bindParam(2, $start_date);
    $stmt->bindParam(3, $end_date);
    $stmt->execute();
    $results = $stmt->fetchAll();

    // Quick dump to show that it worked.
    var_dump($results);

} catch (PDOException $e) {
  echo 'An error occured: ' . $e->getMessage();
}

Here is an Object Oriented method utilizing PDOs that is a bit safer.

Please note that the syntax here is for SQL Server 2012. The main difference is in your SQL statement (you don't need parentheses around the ?s, and you use EXEC rather than CALL).

Also, in this example, the $dbconn object assumes you have a properly configured odbc.ini file and valid ODBC config (this may be tricky depending on your distro... For the working code from this example, I had FreeTDS set up behind it all on a CentOS box. See https://serverfault.com/a/622088 for more.

$dbconn = new PDO("odbc:YOUR_DB", "YOUR_USER", "YOUR_PASS");

  // Set up some useful error reporting.
  $dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    $sql = "EXEC [data_mart].[dbo].[your_stored_procedure] ?,?,?";
    $stmt = $dbconn->prepare($sql);
    $id = 1;
    $start_date = "2015-08-01"
    $end_date = "2015-08-02";
    $stmt->bindParam(1, $id);
    $stmt->bindParam(2, $start_date);
    $stmt->bindParam(3, $end_date);
    $stmt->execute();
    $results = $stmt->fetchAll();

    // Quick dump to show that it worked.
    var_dump($results);

} catch (PDOException $e) {
  echo 'An error occured: ' . $e->getMessage();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文