【问题标题】:execute MSSQL user-defined function in PHP在 PHP 中执行 MSSQL 用户定义的函数
【发布时间】:2017-12-29 18:27:34
【问题描述】:

我需要在远程主机上的 PHP 中执行一个用户定义的函数(通过 odbc)。

函数本身是一个简单的计算,并在 MS SQL Server Studio 中创建如下:

CREATE FUNCTION dbo.__WeightCalculation(@_Length float, @_Width float, @_Height float, @_ShapeType nvarchar(255)) 
RETURNS float AS 

BEGIN
    return (select 
        (CASE
            WHEN @_ShapeType  = 'A'
            THEN (((@_Width * @_Height * 0.5) / 100) * @_Length) / 1000 
            WHEN @_ShapeType IN ('B', 'C', 'D', 'E') 
            THEN (((@_Width * @_Height * 0.75) / 100) * @_Length) / 1000 
            ELSE 'nA'
        END) as THIS_WEIGHT)
END;

我已经能够验证此函数是否正常工作并通过执行返回预期结果

select dbo.__WeightCalculation(10, 20, 30, 'A');


----------------------
0,03

(1 Zeile(n) betroffen)

在管理工作室中。

但是,我无法以除此之外的任何其他方式执行此功能。

当尝试通过网络服务器上的 CLI 运行该功能时,即

user@server:~/tmp# isql dsn usr pwd
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> select dbo.__WeightCalculation(10, 20, 30, 'A');
[ISQL]ERROR: Could not SQLExecute
SQL>

会提示[ISQL]ERROR: Could not SQLExecute。 当尝试从 PHP 脚本运行该函数时,即

$connect = odbc_connect($dsn, $user, $pw);
$query = "SELECT dbo.__WeightCalculation(10, 20, 30, 'A')";
$result = odbc_exec($connect, $query);
$row = odbc_fetch_array($result);
echo '<pre>';
print_r($row);
echo '</pre>';

...可以在服务器错误日志中找到以下内容:

mod_fcgid:stderr:PHP 警告:odbc_exec():SQL 错误:[FreeTDS][SQL 服务器]找不到“dbo”列或用户定义的列 函数或聚合“dbo.__WeightCalculation”,或 名称有歧义。,SQL 状态 37000 在 SQLExecDirect 中 /var/www/web/test/odbc.php 第 14 行

除此之外,我还尝试使用 DECLARE EXEC SELECT 执行该函数,该函数在 SQL Studio 中也可以正常工作,但不是通过 CLI 或 PHP。

需要单独绑定参数和执行函数吗?非常感谢任何有关如何通过 PHP 执行 MSSQL 用户定义函数的提示(因为 CLI 仅用于测试/验证)。

请注意:

  1. 函数调用显然只是更大查询的一部分
  2. 实际场景/用例是 Magento CE 1.9.x 的产品导入(约 20k 产品),使用 MAGMI 在远程服务器上进行 odbc 连接的能力。然而,根据 MA​​GMI 的 wiki,这需要将整个语句放在单个 .sql 文件中(由于到目前为止这不起作用,我开始深入挖掘并遇到上述基本问题,因此我决定在这里而不是在magento.stackexchange.com)
  3. 创建函数、在 SQL Studio 中运行查询以及通过 ODBC 连接的用户是相同的,即 sa

【问题讨论】:

  • 您是否使用与创建函数相同的用户帐户运行。也许 dbo 不对。
  • 嘿@John Kane - 是的,我错过了那个信息。我是 SQL Studio 和通过 ODBC 连接的远程服务器上的同一个用户,即 sa (我知道,使用该用户不是最好的主意,但这就是我从远程服务器管理员那里得到的全部内容,所以远)
  • @ChristophFarnleitner,确保数据库上下文与 SSMS 相同。
  • 嘿@DanGuzman - 我认为这是不可能的 - 或者我没有完全理解你的意思。如果我创建像 CREATE FUNCTION [dbname].dbo.functionname() 这样的函数,我会得到“'CREATE / ALTER FUNCTION',数据库名称不能指定为对象名称的前缀。”作为一个错误
  • 问题的一个常见原因是使用不带引号的混合大小写标识符,因为某些工具会引用包装这些标识符,导致WeightCalculation vs weightcalculation vs WEIGHTCALCULATION,没有一个匹配其他。也就是说,您可能会发现 {[?=]call procedure-name[([parameter][,[parameter]]...)]} + 的 MSDN 文档很有帮助。

标签: php sql-server-2012 odbc user-defined-functions isql


【解决方案1】:

嗯,有一次它会打击你,对吧? ;)

我的函数,因为没有另外指定,是在数据库master 中创建的。事实上,我不能告诉你是否总是这样(至少当你以 sa 登录时)——如果有人能回答这个问题,可能会很有趣。

但是,为特定表创建函数的最初想法(我认为,@DanGuzman 在某些时候也考虑过这一点?)是正确的,正如我所做的那样,是错误的,即——

CREATE FUNCTION [databasename].dbo.functionname(@params)
  ...
GO

-- 不起作用,而--

USE [databasename];
GO
CREATE FUNCTION dbo.functionname(@params)
  ...
GO

--确实。

【讨论】:

    猜你喜欢
    • 2012-11-22
    • 2023-04-10
    • 2015-07-12
    • 2021-12-18
    • 2020-10-15
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 2012-10-24
    相关资源
    最近更新 更多