printf("ho_tari\n");
oracle sql (2) 본문
/*
2일차
- select 기본 질의
-where 절 : 정확하고 다양하게 결과를 출력하기 위한 조건절
기본 구조
select 컬럼명
from 테이블
[where 조건식] <- 선택
[order by ASC, DESC] <- 선택
*/
-- emp 테이블의 모든 컬럼 출력
SELECT * FROM emp;
-- 조건 : 부서번호가 30인 데이터만 출력
-- 조건 -> where (위치 : from 다음에 코딩)
/*
= : 대입연산자x, 비교연산자의 같다 의미
*/
SELECT * FROM emp WHERE deptno = 30;
/*
조건식을 여러개 사용할 경우 : 논리연산자 AND, OR
AND : 조건식의 조건이 모두 참인 경우 참
OR : 조건식의 조건이 한개라도 참인 경우 참
*/
-- 부서번호가 30이면서 직업이 'salesman'인 데이터를 출력
SELECT * FROM emp WHERE deptno = 30 AND job = 'SALESMAN'; -- salesman은 문자이므로 ''안에 작성
-- 사원번호가 7499이고, 부서번호가 30인 사원 정보 출력
SELECT * FROM emp WHERE empno = 7499 AND deptno = 30;
-- 부서번호가 30이거나, 직업이 'CLERK'인 사원 정보 출력
SELECT * FROM emp WHERE deptno = 30 OR job = 'CLERK';
-- 부서번호가 30이거나, 직업이 'CLERK'인 사원 정보를 부서별로 1. 오름차순, 2. 내림차순 정렬 출력
-- 1.
SELECT * FROM emp WHERE deptno = 30 OR job = 'CLERK' ORDER BY deptno ASC;
-- 2.
SELECT * FROM emp WHERE deptno = 30 OR job = 'CLERK' ORDER BY deptno DESC;
/*
연산자
- 산술연산자 : +, -, *, /
- 비교연산자 : >, >=, <, <=
1. 숫자 데이터 비교
2. 문자열 비교
- 등가비교연산자 : =, !=, <>, ^=
- 논리부정연산자 : NOT
- IN연산자 : OR연산자를 대신해 사용 -> IN연산자를 통해 특정열에 대한 조건을 여러개 지정
기본코드
select 컬럼명
from 테이블
where 컬럼명 IN (데이터1, 데이터2, ... , 데이터n);
- BETWEEN A AND B 연산자 : 특정 컬럼의 최소값과 최대값의 범위를 지정
기본코드
select 컬럼명
from 테이블
where 컬럼명 BETWEEN 최소값 AND 최대값;
- LIKE연산자 / 와일드카드(_, %) : 일부 문자열이 포함된 데이터를 검색할 때 사용
1. 와일드카드 _ : 어떤값이든 상관없이 한개의 문자 데이터를 의미
2. 와일드카드 % : 길이와 상관없이(문자가 없는 경우도 포함) 모든 문자 데이터를 의미
3. 와일드카드 문자가 데이터 일부에 포함이 되어있는 경우 : 'A_A' 검색
select 컬럼명
from 테이블명
where 컬럼명 LIKE 'A\_A%' ESCAPE '\';
- IS NULL 연산자 : 특정 컬럼 또는 결과 값이 NULL인지의 여부를 확인
1. IS NULL, IS NOT NULL : 데이터가 NULL인지 아닌지의 확인 용도로 주로 사용
2. AND, OR연산자와 IS NULL
- 집합연산자 : 조회한 결과를 하나의 집합처럼 다룰 수 있다. 두개이상의 select문의 결과 값을 하나로 연결할 때도 사용
종류
1. UNION : 연결된 select문의 결과값을 합집합으로 묶어준다. 결과값은 중복제거를 해준다.
2. UNION ALL : 연결된 select문의 결과값을 합집합으로 묶어준다. 결과값은 중복제거를 안한다.
3. MINUS : 먼저 작성한 select문의 결과값에서 다음 select문의 결과값을 차집합 처리
4. INTERSECT : 교집합
- 연산자우선순위
산술연산자((*, /) > (+, -)) > 비교연산자((대소비교 > (IS NULL, LIKE, IN))) > BETWEEN 연산자 > NOT > AND > OR >
*/
-- 산술연산자
SELECT * FROM emp WHERE sal*12 = 36000;
-- 비교연산자 : 숫자 비교1
SELECT * FROM emp WHERE sal >= 3000;
-- 비교연산자 숫자 비교 2
-- 급여가 2500 이상이고, 직업이 'ANALYST'인 사원 정보 출력
SELECT * FROM emp WHERE sal >= 2500 AND job = 'ANALYST';
-- 비교연산자 : 문자열 비교 1 (비교 문자열이 하나인 경우)
-- 첫문자가 'F' 이거나 'F' 다음의 철자로 된 이름이 출력
SELECT * FROM emp WHERE ename >= 'F';
-- 비교연산자 : 문자열 비교 2 (비교 문자열이 여러개인 경우)
-- 'FORZ'를 포함한 문자열보다 알파벳 순서가 앞에 있는 이름을 줄력
SELECT * FROM emp WHERE ename <= 'FORZ';
-- 등가비교연산자
SELECT * FROM emp WHERE sal != 3000;
SELECT * FROM emp WHERE sal <> 3000;
SELECT * FROM emp WHERE sal ^= 3000;
-- 논리부정연산자
-- NOT연산자와 IN, BETWEEN, IS NULL연산자와 복합적으로 사용
SELECT * FROM emp WHERE NOT sal = 3000;
-- IN연산자
-- OR연산자 : where 조건과 비교연산자, 등가비교연산자를 사용
SELECT * FROM emp WHERE job = 'MANAGER' OR job = 'SALESMAN' OR job = 'CLERK';
-- IN연산자
SELECT * FROM emp WHERE job IN ('MANAGER', 'SALESMAN', 'CLERK');
-- AND연산자 : where 조건과 비교연산자, 등가비교연산자를 사용
SELECT * FROM emp WHERE job != 'MANAGER' AND job <> 'SALESMAN' AND job ^= 'CLERK';
-- AND -> IN연산자
SELECT * FROM emp WHERE job NOT IN ('MANAGER', 'SALESMAN', 'CLERK');
-- BETWEEN AND
-- 대소비교연산자와 AND 연산자
SELECT * FROM emp WHERE sal >= 2000 AND sal <= 3000;
-- 대소비교연산자와 AND 연산자 -> BETWEEN AND
SELECT * FROM emp WHERE sal BETWEEN 2000 AND 3000;
-- 급여 컬럼이 2000 ~ 3000 사이 이외의 값을 가진 데이터 출력 (BETWEEN AND 이용)
SELECT * FROM emp WHERE sal NOT BETWEEN 2000 AND 3000;
-- LIKE, _, %
-- 사원 이름이 대문자 S로 시작하는 데이터 출력
SELECT * FROM emp WHERE ename LIKE 'S%';
-- 사원 이름의 두번째 글자가 L인 사원 출력
SELECT * FROM emp WHERE ename LIKE '_L%';
-- 이름에 'LA'가 포함된 사원의 데이터 출력
SELECT * FROM emp WHERE ename LIKE '%LA%';
-- IS NULL 연산자 : NULL (데이터값이 비어있는 상태라는 특수한 형태)
SELECT ename, sal, sal*12+comm AS ANNSAL, comm from emp;
--NULL은 어떤값인지를 모르기 때문에 결과를 찾아올 수 없다. (비교할 값 자체가 존재 x)
SELECT * FROM emp WHERE comm = NULL;
-- IS NULL : comm 컬럼의 값이 존재하지 않는 데이터만 출력
SELECT * FROM emp WHERE comm IS NULL;
-- comm 컬럼의 값이 NULL이 아닌 데이터만 출력
SELECT * FROM emp WHERE comm IS NOT NULL;
-- AND, OR연산자와 IS NULL
SELECT * FROM emp WHERE sal > NULL OR comm IS NULL;
SELECT * FROM emp WHERE sal > NULL AND comm IS NULL;
-- 집합연산자 : UNION
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 20;
-- 집합연산자 : UNION(컬럼의 개수가 다를 때)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION
SELECT empno, ename, sal FROM emp WHERE deptno = 20;
-- 집합연산자 : UNION(컬럼의 자료형이 다를 경우)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION
SELECT ename, empno, sal, deptno FROM emp WHERE deptno = 20;
-- 집합연산자 : UNION(컬럼의 이름이 다르고, 컬럼의 개수와 자료형이 같을 경우) -> 첫번째 select 기준으로 출력
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION
SELECT sal, job, deptno, sal FROM emp WHERE deptno = 20;
-- 집합연산자 : UNION(출력 결과가 같은 경우 : 중복데이터 제거)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10;
-- 집합연산자 : UNION ALL(출력 결과가 같은 경우 : 중복데이터 출력)
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10
UNION ALL
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10;
-- 집합연산자 : MINUS(차집합)
SELECT empno, ename, sal, deptno FROM emp
MINUS
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10;
-- 집합연산자 : INTERSECT(교집합)
SELECT empno, ename, sal, deptno FROM emp
INTERSECT
SELECT empno, ename, sal, deptno FROM emp WHERE deptno = 10;
/*
함수
- 내장함수 : 오라클에서 기본적으로 제공되는 함수
1. 단일행함수 : 데이터가 한행씩 입력되고 입력된 한 행당 결과가 나오는 함수
2. 다중행함수 : 여러 행이 입력되고 하나의 행으로 결과가 나오는 함수
- 사용자정의함수 : 사용자 필요에 의해 작성되는 함수
- 문자를 가공하는 문자함수
1. 대소문자를 바꿔주는 함수 : upper, lower, initcap
2. 문자열 길이 : length, lengthb
3. 문자열 일부를 추출 : substr(문자열 데이터, 시작위치, 추출길이)
4. 특정문자의 위치를 찾기 : instr
기본구조
INSTR([대상문자열 데이터(필수)], [위치를 찾으려는 부분 문자(필수)], [위치를 찾기 시작할 대상 문자열데이터 위치(선택)])
5. 특정문자를 다른 문자 치환 : replace
기본구조
REPLACE([문자열데이터 또는 컬럼명], [찾는문자(필수)], [대체문자(선택)])
6. 데이터의 빈공간을 특정 문자로 채운다 : LPAD(Left Padding), RPAD(Right Padding)
기본구조
LPAD([문자열데이터 또는 컬럼명(필수)}, [데이터자릿수(필수)], [빈공간 채울 문자(선택)])
RPAD([문자열데이터 또는 컬럼명(필수)}, [데이터자릿수(필수)], [빈공간 채울 문자(선택)])
7. 두 문자열을 합치는 함수 : concat
8. 두 문자열을 연결하는 연산자 : ||
9. 특정 문자를 지우는 함수 : trim, ltrim, rtrim
기본구조
trim([삭제옵션(선택)], [삭제할 문자(선택)] from [원본문자열(필수)])
- 삭제옵션 : LEADING(왼쪽), TRAILING(오른쪽), BOTH(양쪽)
ltrim([원본문자열(필수)], [삭제할 문자집합(선택)]) : 원본문자의 왼쪽에서 삭제할 문자열 지정
rtrim([원본문자열(필수)], [삭제할 문자집합(선택)]) : 원본문자의 오른쪽에서 삭제할 문자열 지정
*/
-- 1. 대소문자를 바꿔주는 함수 : upper, lower, initcap
SELECT ename, upper(ename), lower(ename), initcap(ename) FROM emp;
-- 실제 사용 예
SELECT * FROM emp WHERE ename = 'smith';
SELECT * FROM emp WHERE upper(ename) = upper('smith');
SELECT * FROM emp WHERE upper(ename) = lower('smith');
-- 사원이름에 smith 단어를 포함한 데이터 출력
SELECT * FROM emp WHERE upper(ename) LIKE upper('%smith%');
-- 2. 문자열 길이 : length
SELECT ename, length(ename) FROM emp;
-- 사원이름의 길이가 5 이상인 사원 출력
SELECT ename, length(ename) FROM emp WHERE length(ename) >= 5;
-- 2. 문자열 길이 : lengthb
SELECT ename, length(ename), lengthb(ename) FROM emp;
/*
dual 테이블
- dummy 테이블
- 연산이나 함수의 단일 결과를 확인할 때 사용하는 테이블
*/
SELECT length('한글'), lengthb('한글') FROM dual;
-- 3. 문자열 일부를 추출 : substr
SELECT job, substr(job, 1, 2), substr(job, 3, 2), substr(job, 5) FROM emp;
-- 실제 사용 예 : subste과 length 함께 사용
SELECT job, substr(job, 1, 5) FROM emp;
SELECT job, substr(job, 1) FROM emp;
-- -length() : 오른쪽끝에서부터 왼쪽으로 인덱스 부여
-- -5 인덱스부터 끝까지 출력
SELECT job, substr(job, -length(job)) FROM emp;
SELECT job, substr(job, length(job)) FROM emp;
-- -5 인덱스부터 2글자까지 출력
SELECT job, substr(job, -length(job), 2) FROM emp;
-- -3 인덱스부터 끝까지 출력
SELECT job, substr(job, -3) FROM emp;
-- 4. 특정문자의 위치를 찾기 : instr
SELECT instr('HELLO, ORACLE!', 'L') AS INSTR_1, -- 처음부터 검색해서 첫번째 'L'을 검색
instr('HELLO, ORACLE!', 'L', 5) AS INSTR_2, -- 5번째 위치부터 검색해서 첫번째 'L'을 검색
instr('HELLO, ORACLE!', 'L', 2, 2) AS INSTR_3 -- 2번째 위치부터 검색해서 두번째 'L'을 검색
FROM dual;
-- 실제 사용 예 : instr 과 LIKE, WHERE절 함께 사용
-- instr 함수로 사원이름에 s가 있는 데이터 출력
SELECT * FROM emp WHERE instr(ename, 'S') != 0;
SELECT * FROM emp WHERE instr(ename, 'S') > 0;
-- LIKE연산자로 사원이름에 s가 있는 데이터 출력
SELECT * FROM emp WHERE ename LIKE '%S%';
-- 5. 특정문자를 다른 문자 치환 : replace
SELECT '010-1111-1111' AS re_before,
replace('010-1111-1111', '-', '/') AS re_1,
replace('010-1111-1111', '-') AS re_2
FROM dual;
-- 6. 데이터의 빈공간을 특정 문자로 채운다 : LPAD(Left Padding), RPAD(Right Padding)
SELECT 'Oracle',
LPAD('Oracle', 10, '#') AS LPAD_1, -- 전체 10자리를 만들고 왼쪽의 빈공간을 '#'으로 채운다
RPAD('Oracle', 10, '*') AS RPAD_1, -- 전체 10자리를 만들고 오른쪽의 빈공간을 '*'으로 채운다
LPAD('Oracle', 10) AS LPAD_2, -- 전체 10자리를 만들고 왼쪽의 빈공간을 공백으로 채운다
RPAD('Oracle', 10) AS RPAD_2 -- 전체 10자리를 만들고 오른쪽의 빈공간을 공백으로 채운다
FROM dual;
-- 실제 사용 예 : RPAD로 주민번호 가리기
SELECT
RPAD('970101-', 14, '*') AS RPAD_1,
RPAD('010-1234-', 13, '*') AS RPAD_2
FROM dual;
-- 7. 두 문자열을 합치는 함수 : concat
SELECT concat(empno, ename),
concat(empno, concat(' : ', ename))
FROM emp
WHERE ename = 'SMITH';
-- 8. 두 문자열을 연결하는 연산자 : ||
SELECT empno || ename,
empno || ' : ' || ename FROM emp WHERE ename = 'SMITH';
-- 9. 특정 문자를 지우는 함수 : trim, ltrim, rtrim
-- trim (삭제할 문자가 없을 경우)
SELECT '[' || trim('--Oracle--') || ']' AS trim_trim,
'[' || trim(LEADING FROM '--Oracle--') || ']' AS trim_leading,
'[' || trim(TRAILING FROM '--Oracle--') || ']' AS trim_trailing,
'[' || trim(BOTH FROM '--Oracle--') || ']' AS trim_both
FROM dual;
SELECT '[' || trim(' --Oracle-- ') || ']' AS trim_trim,
'[' || trim(LEADING FROM ' --Oracle-- ') || ']' AS trim_leading,
'[' || trim(TRAILING FROM ' --Oracle-- ') || ']' AS trim_trailing,
'[' || trim(BOTH FROM ' --Oracle-- ') || ']' AS trim_both
FROM dual;
-- trim (삭제할 문자가 없을 경우)
SELECT '[' || trim('-' FROM ' --Oracle-- ') || ']' AS trim_trim,
'[' || trim(LEADING '-' FROM ' --Oracle-- ') || ']' AS trim_leading,
'[' || trim(TRAILING '-' FROM ' --Oracle-- ') || ']' AS trim_trailing,
'[' || trim(BOTH '-' FROM ' --Oracle-- ') || ']' AS trim_both
FROM dual;
SELECT '[' || trim('-' FROM '--Oracle--') || ']' AS trim_trim,
'[' || trim(LEADING '-' FROM '--Oracle--') || ']' AS trim_leading,
'[' || trim(TRAILING '-' FROM '--Oracle--') || ']' AS trim_trailing,
'[' || trim(BOTH '-' FROM '--Oracle--') || ']' AS trim_both
FROM dual;
-- ltrim, rtrim
SELECT '[' || trim(' --Oracle-- ') || ']' AS trim_trim,
'[' || ltrim(' --Oracle-- ') || ']' AS trim_l,
'[' || ltrim('<--Oracle-->', '-<') || ']' AS trim_l2, -- (-, <)를 조합해서 모든 경우를 삭제
'[' || rtrim(' --Oracle-- ') || ']' AS trim_r,
'[' || rtrim('<--Oracle-->', '>-') || ']' AS trim_r2
FROM dual;
/*
숫자함수
- 데이터를 연산하고 수치 조정
1. 특정위치에서 반올림 : round
2. 버림함수 : trunc
3. 지정된 숫자보다 큰 정수 중 가장 작은 정수를 반환 : ceil
4. 지정된 숫자보다 작은 정수 중 가장 큰 정수를 반환 : floor
5. 나머지 함수 : mod
*/
-- 1. 특정위치에서 반올림 : round
SELECT round(1234.5678) AS r_1,
round(1234.5678, 0) AS r_2,
round(1234.5678, 1) AS r_3,
round(1234.5678, 2) AS r_4,
round(1234.5678, -1) AS r_5, -- -기호는 정수부분을 의미
round(1234.5678, -2) AS r_6
FROM dual;
-- 2. 버림함수 : trunc
SELECT trunc(1234.5678) AS r_1,
trunc(1234.5678, 0) AS r_2,
trunc(1234.5678, 1) AS r_3,
trunc(1234.5678, 2) AS r_4,
trunc(1234.5678, -1) AS r_5, -- -기호는 정수부분을 의미
trunc(1234.5678, -2) AS r_6
FROM dual;
-- 3. 지정된 숫자보다 큰 정수 중 가장 작은 정수를 반환 : ceil
-- 4. 지정된 숫자보다 작은 정수 중 가장 큰 정수를 반환 : floor
SELECT ceil(3.14),
floor(3.14),
ceil(-3.14), -- -3, -2, -1, ...
floor(-3.14) -- -4, -5, -6, ...
FROM dual;
-- 5. 나머지 함수 : mod
SELECT mod(15, 6),
mod(10, 2)
FROM dual;
/*
날짜함수
- 날짜 데이터를 다루는 함수
1. 시스템 날짜 출력 : sysdate
2. 몇 개월 이후 출력 : add_months
3. 두 날짜간의 개월 수 차이 : months_between
4. 돌아오는 요일 : next_day
5. 달의 마지막 날짜 : last_day
6. 날짜의 반올림, 버림 : round, trunc
*/
-- 1. 시스템 날짜 출력 : sysdate
SELECT sysdate AS now, sysdate - 1 AS yesterday, sysdate + 1 AS tomorrow FROM dual;
-- 2. 몇 개월 이후 출력 : add_months
SELECT sysdate, add_months(sysdate, 3) FROM dual;
-- 실제 사용 : add_months
SELECT empno, ename, hiredate, sysdate FROM emp
WHERE add_months(hiredate, 500) > sysdate; -- scott 데이터가 만들어진 시기를 기준으로 검색
-- 3. 두 날짜간의 개월 수 차이 : months_between
SELECT empno, ename, hiredate, sysdate,
months_between(hiredate, sysdate) AS m1,
months_between(sysdate, hiredate) AS m2,
trunc(months_between(sysdate, hiredate)) AS m3
FROM emp;
-- 4. 돌아오는 요일 : next_day
-- 5. 달의 마지막 날짜 : last_day
SELECT sysdate, next_day(sysdate, '월요일'), last_day(sysdate) FROM dual;
-- 6. 날짜의 반올림, 버림 : round, trunc
SELECT sysdate,
round(sysdate, 'CC') AS f_cc, -- 2050년을 기준으로 년도 이하이면 2001년으로 처리
round(sysdate, 'YYYY') AS f_yyyy, -- 모든 년도를 7월 1일을 기준으로 7월 1일 이상이면 1년을 더해줌
round(sysdate, 'Q') AS f_q, -- 각 분기의 두번째달의 16일 기준
round(sysdate, 'DDD') AS f_ddd, -- 해당일의 정오를 기준
round(sysdate, 'HH') AS f_hh -- 해당일의 시간을 기준
FROM dual;
/*
형변환 함수
- 자료형 변환 함수
1. 숫자 또는 날짜 -> 문자 : to_char
CC : 세기
YY : 2자리 년도
YYYY : 4자리 년도
MM : 월
MON : 언어별 월 이름
DD : 일
DDD : 1년 중 며칠
DY : 언어별 요일이름 약자
DAY : 언어별 요일이름 전체
W : 1년 중 몇 째주
HH2 : 24시간 표현
HH, HH12 : 12시간 표현
MI : 분
SS : 초
AM, PM, A.M, P.M : 오전, 오후
9 : 숫자
0 : 빈자리 0으로 채움
$ : 달러표시 붙여서 출력
L : 지역 화폐
. : 소수점
, : 천단위 기호
2. 문자 -> 숫자 : to_number
3. 문자 -> 날짜 : to_date
*/
-- 1. 숫자 또는 날짜 -> 문자 : to_char
SELECT to_char(sysdate, 'YYYY/MM/DD HH24:MI:SS') FROM dual;
SELECT to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') FROM dual;
-- 2. 문자 -> 숫자 : to_number
SELECT 1300 - '1500', '1300' + '1500' FROM dual; -- 묵시적형변환(자동형변환)
SELECT '1,300' - '1,500' FROM dual;
SELECT to_number('1,300', '999,999') - to_number('1,500', '999,999') FROM dual;
-- 3. 문자 -> 날짜 : to_date
SELECT to_date('2023-07-25', 'YYYY-MM-DD') AS date_1,
to_date('20230725', 'YYYY-MM-DD') AS date_2,
to_date('2023/07/25', 'YYYY-MM-DD') AS date_3,
to_date('2023-07-25', 'YY-MM-DD') AS date_4
FROM dual;
/*
NULL 처리 함수
1. NVL(a, b) : a의 값이 NULL이면 b로 대체
2. NVL2(a, b, c) : a의 값이 NULL이 아니면 b로 출력, NULL이면 c로 출력
3. NULLIF(a, b) : a와 b가 같으면 NULL 출력, 다르면 a 출력
*/
-- 1. NVL(a, b) : a의 값이 NULL이면 b로 대체
SELECT empno, ename, sal, comm, sal+comm, NVL(comm, 0), sal+NVL(comm, 0) FROM emp;
-- 2. NVL2(a, b, c) : a의 값이 NULL이 아니면 b로 출력, NULL이면 c로 출력
select empno, ename, sal, comm, NVL2(comm, 'o', 'x'), NVL2(comm, sal*12+comm, sal*12) FROM emp;
-- 3. NULLIF(a, b) : a와 b가 같으면 NULL 출력, 다르면 a 출력
select # from v$sql;
'SQL' 카테고리의 다른 글
oracle sql (example problem) (0) | 2023.09.02 |
---|---|
oracle sql (5) (0) | 2023.09.02 |
oracle sql (4) (0) | 2023.09.02 |
oracle sql (3) (0) | 2023.09.02 |
oracle sql (1) (0) | 2023.09.02 |