将行引用作为MySQL函数输入参数传递

时间:2013-12-26 20:28:31

标签: mysql sql pass-by-reference

我正在创建一个函数,可以根据可用信息从用户帐户记录中轻松检索客户端名称。除id以外的所有帐户字段都是可选的,可能是空白的,因此这会连续检查各个标识列,直到找到一个,并返回id作为最后一个结果。

CREATE FUNCTION ACCOUNT_NAME(
    fname varchar(50),
    lname varchar(50),
    company varchar(50),
    email varchar(50),
    id int(10) unsigned
)
RETURNS VARCHAR(100) DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER
RETURN
    IF( TRIM(CONCAT(fname, ' ', lname)) <> '',
        TRIM(CONCAT(fname, ' ', lname)),
        IF( company <> '',
            company,
            IF(email <> '', email, id)
        )
    )
;

这很好用,但我需要将每一列单独传递给函数,即:

SELECT ACCOUNT_NAME(
    a.first_name,
    a.last_name,
    a.company,
    a.email,
    a.id
) AS client_name
FROM accounts AS a WHERE 1;

这不仅繁琐,将来修改或扩展此功能将非常困难,可能需要查找和更新每个调用以及定义本身。

是否可以将对整个行结果的引用作为输入参数传递?理想情况下,我想做这样的事情:

CREATE FUNCTION ACCOUNT_NAME(row result)
    RETURNS VARCHAR(100) DETERMINISTIC CONTAINS SQL SQL SECURITY INVOKER
RETURN
    IF( TRIM(CONCAT(row.first_name, ' ', row.last_name)) <> '',
        TRIM(CONCAT(row.first_name, ' ', row.last_name)),
        IF( row.company <> '',
            row.company,
            IF(row.email <> '', row.email, row.id)
        )
    )
;

SELECT ACCOUNT_NAME(a.*) AS client_name
FROM accounts AS a WHERE 1;

2 个答案:

答案 0 :(得分:1)

您的文字问题的答案是否定的 - 存储过程或存储函数的参数不能是对行对象的引用。它们必须是标量数据类型,例如用于在表中定义列的数据类型。

您可以改为定义VIEW:

CREATE OR REPLACE VIEW accounts_view (id, client_name) AS
  SELECT id, COALESCE(
    NULLIF(CONCAT(fname, ' ', lname), ' '),
    NULLIF(company, ''),
    NULLIF(email, ''),
    id) AS client_name
  FROM accounts;

然后您可以更简单地查询:

SELECT client_name
FROM accounts_view;

如果您想要更改格式化client_name的方式,那么只需使用另一个CREATE OR REPLACE VIEW语句即可。重写视图定义非常快。

答案 1 :(得分:0)

SQL不是文本操作的好语言。 SQL是存储和检索数据的好语言。

在应用程序代码中保留“业务逻辑”。也就是说,有一层代码(使用您正在使用的语言)执行Account_Name操作。

“客户端”可以使用行引用或任何有意义的方式调用Layer。设计API以保持其清洁。然后,Layer执行任何需要的脏工作来实现这样的功能。它甚至可能不得不跑到多个桌子上来收集碎片。

例如,今天您在同一个表中有email。如果明天你将它放在其他地方,那么将图层更改为使用SELECTs执行两个SELECT或(更好)一个JOIN