【发布时间】:2018-09-15 09:40:14
【问题描述】:
对于我想要完成的工作来说,这可能是一个糟糕的用例,但我已经阅读了几十页,我无法确定这在 Oracle 中是否可行。
我想完成类似于另一个 stackoverflow 问题的事情:How to chain calls in a pl/sql object type of functions returning SELF
在我的代码中,我有一个名为 parseName 的类型,它带有一个构造函数和 3 个成员函数:getFirstName、getMiddleName、getLastName。我想要第四个成员函数:cleanString,它删除不在 A-Z 或 a-z 之间的所有字符。
调用示例:
SELECT parseName('John123 Doe').getFirstName().cleanString()
FROM dual;
SELECT parseName('John123 Doe').getFirstName()
FROM dual;
这是我目前所写的类型。
CREATE OR REPLACE TYPE parseName AS OBJECT
(
g_name VARCHAR2(255),
g_parts NUMBER,
g_first_name VARCHAR2(255),
g_middle_name VARCHAR2(1),
g_last_name VARCHAR2(255),
-- constructor function
CONSTRUCTOR FUNCTION parseName
(p_name IN VARCHAR2)
RETURN self AS result,
-- member functions
MEMBER FUNCTION getFirstName RETURN VARCHAR2,
MEMBER FUNCTION getMiddleName RETURN VARCHAR2,
MEMBER FUNCTION getLastName RETURN VARCHAR2
);
/
SHOW ERRORS
/
CREATE OR REPLACE TYPE BODY parseName IS
-- populateValues
CONSTRUCTOR FUNCTION parseName
(p_name IN VARCHAR2)
RETURN self AS result
IS
-- other variables
v_name VARCHAR2(255);
v_length NUMBER;
v_parts NUMBER;
v_instr NUMBER;
BEGIN
-- save off input
v_name := TRIM(p_name);
-- check
IF v_name IS NULL THEN
self.g_first_name := 'Unknown';
self.g_middle_name := ' ';
self.g_last_name := 'Unknown';
RETURN;
END IF;
-- otherwise, fill our global
self.g_name := v_name;
-- exit
RETURN;
END;
/* getFirstName */
/* --------------------------------------- */
MEMBER FUNCTION getFirstName
RETURN VARCHAR2
IS
v_parts NUMBER;
BEGIN
-- did we get a null on construct?
IF self.g_first_name IS NOT NULL THEN
RETURN self.g_first_name;
END IF;
-- how many spaces do we have?
v_parts := LENGTH(self.g_name) - LENGTH(REPLACE(self.g_name,' ',''));
-- if 0 spaces, return the name
IF v_parts = 0 THEN
RETURN self.g_name;
-- else, return everything up to the space
ELSE
RETURN TRIM(SUBSTR(self.g_name,1, INSTR(self.g_name,' ',1) ));
END IF;
END getFirstName;
/* getMiddleName */
/* --------------------------------------- */
MEMBER FUNCTION getMiddleName
RETURN VARCHAR2
IS
v_parts NUMBER;
v_instr2 NUMBER;
v_instr1 NUMBER;
BEGIN
-- did we get a null on construct?
IF self.g_middle_name IS NOT NULL THEN
RETURN NULL;
END IF;
-- how many spaces do we have?
v_parts := LENGTH(self.g_name) - LENGTH(REPLACE(self.g_name,' ',''));
-- if we have zero spaces, we only have a first name, return null
IF v_parts = 0 THEN
RETURN NULL;
-- don't do middle if we only have 1 space
ELSIF v_parts = 1 THEN
RETURN NULL;
-- else, we've got more than one, so grab between space 1 and 2
ELSE
v_instr2 := INSTR(self.g_name,' ',1,2);
v_instr1 := INSTR(self.g_name,' ',1,1);
RETURN TRIM( SUBSTR(self.g_name, v_instr1, (v_instr2-v_instr1) ));
END IF;
END getMiddleName;
/* getLastName */
/* --------------------------------------- */
MEMBER FUNCTION getLastName
RETURN VARCHAR2
IS
v_parts NUMBER;
BEGIN
-- did we get a null on construct?
IF self.g_last_name IS NOT NULL THEN
RETURN self.g_last_name;
END IF;
-- how many spaces do we have?
v_parts := LENGTH(self.g_name) - LENGTH(REPLACE(self.g_name,' ',''));
-- if we have zero spaces, we only have a first name, return 'Unknown'
IF v_parts = 0 THEN
RETURN 'Unknown';
-- if have 1 space, the space on is the last name
ELSIF v_parts = 1 THEN
RETURN TRIM( SUBSTR(self.g_name, INSTR(self.g_name,' ',1,1), LENGTH(self.g_name)) );
-- else, we've got more than one, go from 2 to end
ELSE
RETURN TRIM( SUBSTR(self.g_name, INSTR(self.g_name,' ',1,2), LENGTH(self.g_name)) );
END IF;
END getLastName;
END;
/
SHOW ERRORS
/
.
感谢您提供的任何建议。
【问题讨论】:
-
.getFirstName()返回一个字符串(并且您不能在字符串上定义成员函数) - 它需要返回一个parseName对象才能具有链接请求的功能(这样就不会获得名)。为什么不能只把cleanString()当作普通函数,而做cleanString( parseName('John123 Doe').getFirstName() )? -
我绝对可以。这可能就是我最终要走的路线。只是展示我的好奇心。 :) 我确实尝试过创建两个版本的 getFirstName,一个返回 self,一个返回 VARCHAR2,但 Oracle 也不喜欢这样。我收到了错误:ORA-22806: not an object or REF
-
你绝对可以在 PL/SQL 中链接这样的调用(MT0 已经在他的回答中展示了它)。关键是您必须始终遵循数据类型,并且不要尝试在错误的数据类型上调用函数(任何类型的 - 无论是“标准”或用户定义的,类型的成员或其他)。在您的问题中,另一个观察结果是 MEMBER 函数只能在它所属的类型上定义;否则它不是“成员”函数。
标签: oracle function plsql types member