我需要模仿嵌套for循环的功能(或模仿foreach循环)。我在下面有一个查询作为一个例子(请注意,这是一个更复杂的查询的例子 - 为了简单起见)。
SELECT userName from employeeDetails where userName = 'Peter';
足够简单。但是我需要userName的值为变量,以便我可以将此查询嵌套到父查询中。父查询将如此:
SELECT userName from allEmployees;
因此,使用foreach循环的一些sudo代码就是如此:
foreach x as `SELECT userName from allEmployees`
do
SELECT userName from employeeDetails where userName = x;
done
PS - 我正在查询Oracle 10.2.04数据库
更新1 - 对于混乱感到抱歉,但我认为上面的“简单”示例有点简单。我在下面列出了我的整个查询 - 在该查询中,您将在查询的13个不同部分中找到我的名字( CocoaNoob )。我需要在表格中用名称foreach名称替换此硬编码名称。
SELECT SSN, EMP_NAME, HIRE_DT, DEPTID, FULL_PART_TIME,
(CASE WHEN AVAILABLE_VACATION < 0 THEN 0 ELSE AVAILABLE_VACATION END)
AVAILABLE_VACATION
FROM (SELECT 'XXX-XX-' || SUBSTR (A.EMPLID, 6) EMPLID,
A.EMPLID AS SSN,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR (CURRENT_YR_SICK)
ELSE
'As Needed'
END)
CURRENT_YR_SICK,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR (CARRY_OVER_SICK)
ELSE
'As Needed'
END)
CARRY_OVER_SICK,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR ( (CURRENT_YR_SICK + CARRY_OVER_SICK))
ELSE
'As Needed'
END)
TOTAL_SICK,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR (PERSONAL)
ELSE
'As Needed'
END)
PERSONAL,
CURRENT_YR_VACATION,
CARRY_OVER_VACATION,
(CURRENT_YR_VACATION + CARRY_OVER_VACATION) TOTAL_VACATION,
NVL (
(SELECT SUM (NO_DAYS)
FROM HRU_ENT_COFF_DETAILS
WHERE emplid = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND comp_off_type = 'ECOFF'),
'0'
)
EARNED_COMP_OFF,
NVL (
(SELECT SUM (NO_DAYS)
FROM HRU_ENT_COFF_DETAILS
WHERE emplid = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND comp_off_type = 'BLOOD'),
'0'
)
BLOOD_COMP_OFF,
NVL (
(SELECT SUM (NO_DAYS)
FROM HRU_ENT_COFF_DETAILS
WHERE emplid = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND comp_off_type = 'HABITAT'),
'0'
)
HABITAT_COMP_OFF,
NVL (
(SELECT SUM (NO_DAYS)
FROM HRU_ENT_COFF_DETAILS
WHERE emplid = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND comp_off_type = 'HCOFF'),
'0'
)
HOLIDAY_COMP_OFF,
(INITCAP (E.FIRST_NAME) || ' ' || INITCAP (E.LAST_NAME))
AS EMP_NAME,
TO_CHAR (HIRE_DT, 'mm/dd/yyyy') HIRE_DT,
TO_CHAR (REHIRE_DT, 'mm/dd/yyyy') REHIRE_DT,
JOBTITLE,
OFFICER_TITLE,
CLOCK_NBR,
D.DEPTID DEPTID,
FILE_NBR,
D.DESCR DESCR,
(CASE
WHEN FLSA_STATUS = 'E' AND FULL_PART_TIME = 'F'
THEN
'Exempt/Full-Time'
WHEN FLSA_STATUS = 'E' AND FULL_PART_TIME = 'P'
THEN
'Exempt/Part-Time'
WHEN FLSA_STATUS = 'N' AND FULL_PART_TIME = 'F'
THEN
'Non-Exempt/Full-Time'
WHEN FLSA_STATUS = 'N' AND FULL_PART_TIME = 'P'
THEN
'Non-Exempt/Part-Time'
ELSE
''
END)
AS EMP_STATE,
full_part_time,
COFF_ELIGIBLE,
EMP_CAT,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR( ( (CURRENT_YR_SICK + CARRY_OVER_SICK)
- (NVL (
(SELECT SUM (no_days_used)
FROM HRU_ENT_USAGE_HIST
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id =
'__CocoaNoob__')
AND TO_CHAR (
FROM_DATE_USED,
'yyyy'
) =
TO_CHAR (SYSDATE,
'yyyy')
AND entitlement_code IN
('SICK',
'FMS',
'PLS')),
0
))))
ELSE
'As Needed'
END)
AVAILABLE_SICK,
( (CURRENT_YR_VACATION + CARRY_OVER_VACATION)
- (NVL (
(SELECT SUM (no_days_used)
FROM HRU_ENT_USAGE_HIST
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND TO_CHAR (FROM_DATE_USED, 'yyyy') =
TO_CHAR (SYSDATE, 'yyyy')
AND entitlement_code IN
('VACATION', 'FMV', 'PLV')),
0
)))
AVAILABLE_VACATION,
(CASE
WHEN EMP_CAT NOT IN ('EFT-O', 'NEFT-O')
THEN
TO_CHAR( (PERSONAL
- (NVL (
(SELECT SUM (no_days_used)
FROM HRU_ENT_USAGE_HIST
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id =
'__CocoaNoob__')
AND TO_CHAR (
FROM_DATE_USED,
'yyyy'
) =
TO_CHAR (SYSDATE,
'yyyy')
AND entitlement_code IN
('PERSONAL',
'FMP',
'PLP')),
0
))))
ELSE
'As Needed'
END)
AVAILABLE_PERSONAL,
(CASE
WHEN COFF_ELIGIBLE = 'YES'
THEN
TO_CHAR(NVL (
(SELECT (SUM (NO_DAYS)
- NVL (SUM (NO_DAYS_USED), 0))
FROM HRU_ENT_COFF_DETAILS
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id =
'__CocoaNoob__')
AND comp_off_type = 'ECOFF'),
'0'
))
ELSE
'Not Eligible'
END)
AVAILABLE_ECOFF,
(TO_CHAR(NVL (
(SELECT (SUM (NO_DAYS)
- NVL (SUM (NO_DAYS_USED), 0))
FROM HRU_ENT_COFF_DETAILS
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id =
'__CocoaNoob__')
AND comp_off_type = 'HCOFF'),
'0'
)))
AVAILABLE_HCOFF,
(TO_CHAR(NVL (
(SELECT (SUM (NO_DAYS)
- NVL (SUM (NO_DAYS_USED), 0))
FROM HRU_ENT_COFF_DETAILS
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id =
'__CocoaNoob__')
AND comp_off_type = 'BLOOD'),
'0'
)))
AVAILABLE_BCOFF,
(TO_CHAR(NVL (
(SELECT (SUM (NO_DAYS)
- NVL (SUM (NO_DAYS_USED), 0))
FROM HRU_ENT_COFF_DETAILS
WHERE emplid =
(SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND comp_off_type = 'HABITAT'),
'0'
)))
AVAILABLE_HACOFF
FROM HRU_ENTITLEMENTS_MASTER A,
EMPLOYEES E,
DEPTS D,
(SELECT EMPLID,
(CASE
WHEN FLSA_STATUS = 'E'
AND FULL_PART_TIME = 'F'
AND OFFICER_TITLE = 'NONE'
THEN
'EFT-NO'
WHEN FLSA_STATUS = 'E'
AND FULL_PART_TIME = 'F'
AND OFFICER_TITLE != 'NONE'
THEN
'EFT-O'
WHEN FLSA_STATUS = 'E'
AND FULL_PART_TIME = 'P'
AND OFFICER_TITLE = 'NONE'
THEN
'EPT-NO'
WHEN FLSA_STATUS = 'N'
AND FULL_PART_TIME = 'F'
AND OFFICER_TITLE != 'NONE'
THEN
'NEFT-O'
WHEN FLSA_STATUS = 'N'
AND FULL_PART_TIME = 'F'
AND OFFICER_TITLE = 'NONE'
THEN
'NEFT-NO'
WHEN FLSA_STATUS = 'N'
AND FULL_PART_TIME = 'P'
AND OFFICER_TITLE = 'NONE'
THEN
'NEPT-NO'
ELSE
''
END)
AS EMP_CAT,
(CASE
WHEN OFFICER_TITLE IN
('CHAIRMAN & CEO',
'VICE CHAIRMAN & CAO',
'PRESIDENT & COO',
'EVP, TREASURER & CFO',
'EXEC VP, SECRETARY & GEN COUNS',
'EXECUTIVE VICE PRESIDENT',
'SENIOR VP & CIO',
'SENIOR VICE PRESIDENT',
'DIRECTOR',
'FIRST VP/CONTROLLER',
'FIRST VP',
'VICE PRESIDENT')
THEN
'NO'
ELSE
'YES'
END)
COFF_ELIGIBLE
FROM EMPLOYEES
WHERE EMPLID = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')) B
WHERE A.EMPLID = (SELECT emplid
FROM employees
WHERE user_id = '__CocoaNoob__')
AND A.YEAR = '2012'
AND A.EMPLID = E.EMPLID
AND D.DEPTID = E.DEPTID
AND E.EMPLID = B.EMPLID);
答案 0 :(得分:2)
你不能这样做:
SELECT userName
FROM allEmployees a
INNER JOIN employeeDetails b ON a.userName = b.userName
或者如果没有,也许你可以写一个如:
的过程create or replace type varchar_array as table of varchar(10)
procedure doStuff( p_array in varchar_array )
as
temp VARCHAR2;
begin
for i in 1 .. p_array.count
loop
SELECT userName
INTO temp
FROM employeeDetails
WHERE userName = p_array(i);
dbms_output.put_line( temp );
end loop;
end;
答案 1 :(得分:2)
正如我在评论中提到的,您通常希望找到基于集合的解决方案。但是,当我们真正想要运行一系列以程序方式更容易表达的处理时,数据库制造商已经给了我们 cursors (或其他ways to iterate)。游标可能符合这个要求。如果重新构建数据库的范围超出了您的范围,例如将该case / switch逻辑放入表中,则尤其如此。如果光标性能不可接受,则可能需要重新查找基于集合的解决方案。
答案 2 :(得分:1)
为什么不加入这两张桌子?
SELECT userName
FROM employeeDetails d
JOIN allEmployees a USING (userName)
您还可以使用IN
(或EXISTS
)。这可能效率较低,但可能更容易看到发生了什么。
SELECT d.userName
FROM employeeDetails d
WHERE d.userName IN (SELECT a.userName
FROM allEmployees a)
答案 3 :(得分:1)
您尝试做的事情被称为两个表的“连接”。连接的目的是根据某些匹配条件将两个表连接在一起。如果要获取两个表中都有数据的所有行的数据,那就是“内连接”。如果您想要一个表中的所有数据,但第二个表中可能存在或可能不存在数据,那么这就是“外连接”。并且你想要找回任何表中可能存在或不存在数据的结果,这被称为“完全连接”。也许一些例子会很有用。
假设您的表格中包含以下数据:
allEmployees
userName
JOHN
PAUL
GEORGE
PETE
RINGO
employeeDetails
userName lastName instrument
JOHN Lennon guitar
PAUL McCartney bass
GEORGE Harrison guitar
RINGO Starr drums
EARL Scruggs banjo
让我们说你运行以下查询:
select userName, instrument
from allEmployees
inner join employeeDetails
using (userName)
你应该得到以下结果:
userName instrument
JOHN guitar
PAUL bass
GEORGE guitar
RINGO drums
当然,这引出了一个问题“那么PETE和EARL发生了什么?”。答案是内连接要求BOTH表中有数据,并且因为userDetails中没有userName ='PETE'的行,所以没有为该userName返回任何数据。同样,所有员工中都没有userName ='EARL'的行,所以它再见了,Earl。
如果相反,您总是希望返回allEmployees表中的每个用户,如果它们可用,则使用外部联接,方式类似于
select userName, instrument
from allEmployees
left outer join employeeDetails
using (userName)
在这种情况下你会得到像
这样的东西userName instrument
JOHN guitar
PAUL bass
GEORGE guitar
PETE NULL
RINGO drums
又有PETE,又回来了,但没有详细信息。但是,仍然没有EARL,因为EARL在所有员工中都没有一行。
使用FULL JOIN可以获取所有数据,如
select userName, instrument
from allEmployees
full join employeeDetails on (userName)
应该产生类似
的东西userName instrument
JOHN guitar
PAUL bass
GEORGE guitar
PETE NULL
RINGO drums
EARL banjo
我希望这会有所帮助。