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

问题描述 投票:2回答:2

我正在创建一个函数,可以根据可用信息从用户帐户记录中轻松检索客户端名称。除了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;
mysql sql pass-by-reference
2个回答
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语句。重写视图定义非常快。


0
投票

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

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

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

例如,今天你在同一张表中有email。如果明天你把它放在其他地方,那么改变图层做两个SELECTs或(更好)一个SELECTJOIN

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