如何在 PL/SQL 对象类型中链接成员函数
How to Chain Member Functions in a PL/SQL Object Type
对于我想要完成的事情来说,这可能是一个糟糕的用例,但我已经阅读了几十页,但我无法弄清楚这在 Oracle 中是否可行。
我想完成与另一个 Whosebug 问题类似的事情: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
/
.
感谢您提供的任何建议。
I would like to have a fourth member function called: cleanString which removes all characters not between A-Z or a-z.
Example calls:
SELECT parseName('John123 Doe').getFirstName().cleanString()
FROM dual;
当你调用 .getFirstName()
时,期望的是它 return 人的名字(毕竟这是成员函数的名字所说的)并且名字是 VARCHAR2
数据类型。 VARCHAR2
是原始数据类型,不是您可以(以某种方式)扩展为具有 .cleanString()
成员函数的对象。
您可以定义一个 cleanString()
函数:
CREATE FUNCTION cleanString( value VARCHAR2 ) RETURN VARCHAR2
IS
BEGIN
RETURN REGEXP_REPLACE( value, '[^[:alpha:]]+' );
END cleanString;
/
然后调用:
SELECT cleanString( parseName('John123 Doe').getFirstName() )
FROM DUAL;
或者你可以创建一个成员函数来在 return 之前清理名称:
Oracle 11g R2 架构设置:
CREATE OR REPLACE TYPE parseName AS OBJECT
(
g_name VARCHAR2(255),
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 cleanNames RETURN parseName,
MEMBER FUNCTION getFirstName RETURN VARCHAR2,
MEMBER FUNCTION getMiddleName RETURN VARCHAR2,
MEMBER FUNCTION getLastName RETURN VARCHAR2
);
/
CREATE OR REPLACE TYPE BODY parseName IS
-- populateValues
CONSTRUCTOR FUNCTION parseName(p_name IN VARCHAR2) RETURN self AS result
IS
BEGIN
g_name := TRIM(p_name);
g_first_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 1 );
g_middle_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 3 );
g_last_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 4 );
RETURN;
END;
MEMBER FUNCTION cleanNames RETURN parseName
IS
v_name parseName := SELF;
BEGIN
v_name.g_first_name := cleanString( SELF.g_first_name );
v_name.g_middle_name := cleanString( SELF.g_middle_name );
v_name.g_last_name := cleanString( SELF.g_last_name );
RETURN v_name;
END;
MEMBER FUNCTION getFirstName RETURN VARCHAR2
IS
BEGIN
RETURN g_first_name;
END getFirstName;
MEMBER FUNCTION getMiddleName RETURN VARCHAR2
IS
BEGIN
RETURN g_middle_name;
END getMiddleName;
MEMBER FUNCTION getLastName RETURN VARCHAR2
IS
BEGIN
RETURN g_last_name;
END getLastName;
END;
/
查询 1:
SELECT parseName('John123 Doe').getFirstName(),
parseName('John123 Doe').cleanNames().getFirstName()
FROM DUAL
| PARSENAME('JOHN123DOE').GETFIRSTNAME() | PARSENAME('JOHN123DOE').CLEANNAMES().GETFIRSTNAME() |
|----------------------------------------|-----------------------------------------------------|
| John123 | John |
对于我想要完成的事情来说,这可能是一个糟糕的用例,但我已经阅读了几十页,但我无法弄清楚这在 Oracle 中是否可行。
我想完成与另一个 Whosebug 问题类似的事情: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
/
.
感谢您提供的任何建议。
I would like to have a fourth member function called: cleanString which removes all characters not between A-Z or a-z.
Example calls:
SELECT parseName('John123 Doe').getFirstName().cleanString() FROM dual;
当你调用 .getFirstName()
时,期望的是它 return 人的名字(毕竟这是成员函数的名字所说的)并且名字是 VARCHAR2
数据类型。 VARCHAR2
是原始数据类型,不是您可以(以某种方式)扩展为具有 .cleanString()
成员函数的对象。
您可以定义一个 cleanString()
函数:
CREATE FUNCTION cleanString( value VARCHAR2 ) RETURN VARCHAR2
IS
BEGIN
RETURN REGEXP_REPLACE( value, '[^[:alpha:]]+' );
END cleanString;
/
然后调用:
SELECT cleanString( parseName('John123 Doe').getFirstName() )
FROM DUAL;
或者你可以创建一个成员函数来在 return 之前清理名称:
Oracle 11g R2 架构设置:
CREATE OR REPLACE TYPE parseName AS OBJECT
(
g_name VARCHAR2(255),
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 cleanNames RETURN parseName,
MEMBER FUNCTION getFirstName RETURN VARCHAR2,
MEMBER FUNCTION getMiddleName RETURN VARCHAR2,
MEMBER FUNCTION getLastName RETURN VARCHAR2
);
/
CREATE OR REPLACE TYPE BODY parseName IS
-- populateValues
CONSTRUCTOR FUNCTION parseName(p_name IN VARCHAR2) RETURN self AS result
IS
BEGIN
g_name := TRIM(p_name);
g_first_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 1 );
g_middle_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 3 );
g_last_name := REGEXP_SUBSTR( g_name, '^(\S+)\s+((\S*?)\s+)?(.*)$', 1, 1, NULL, 4 );
RETURN;
END;
MEMBER FUNCTION cleanNames RETURN parseName
IS
v_name parseName := SELF;
BEGIN
v_name.g_first_name := cleanString( SELF.g_first_name );
v_name.g_middle_name := cleanString( SELF.g_middle_name );
v_name.g_last_name := cleanString( SELF.g_last_name );
RETURN v_name;
END;
MEMBER FUNCTION getFirstName RETURN VARCHAR2
IS
BEGIN
RETURN g_first_name;
END getFirstName;
MEMBER FUNCTION getMiddleName RETURN VARCHAR2
IS
BEGIN
RETURN g_middle_name;
END getMiddleName;
MEMBER FUNCTION getLastName RETURN VARCHAR2
IS
BEGIN
RETURN g_last_name;
END getLastName;
END;
/
查询 1:
SELECT parseName('John123 Doe').getFirstName(),
parseName('John123 Doe').cleanNames().getFirstName()
FROM DUAL
| PARSENAME('JOHN123DOE').GETFIRSTNAME() | PARSENAME('JOHN123DOE').CLEANNAMES().GETFIRSTNAME() |
|----------------------------------------|-----------------------------------------------------|
| John123 | John |