检查记录是否已存在于数据库中的最快方法是什么。 我没有独特的身份证明。 可以在值之后检查名称,姓氏,出生日期
答案 0 :(得分:2)
通常,检查行是否存在的最快方法是使用SELECT-INTO(隐式游标)语句,而不是显式游标。当找到一行时,始终更快。如果找不到行,SELECT-INTO会引发NO_DATA_FOUND并且异常处理相对较慢。
因此,当您编写代码时,请考虑上下文,考虑数据和使用模式。您是否希望查询通常能找到一行?然后选择SELECT-INTO。你认为通常获取会失败吗?然后使用显式光标。
当然,如@Randy所述,您需要确保拥有正确的索引以确保优化查找。
关于此主题的我blog post应该有助于填写详细信息,并为您提供一些代码来对付这些想法。但我也会在这里发帖以使其更容易。
CREATE OR REPLACE PACKAGE tmr
IS
PROCEDURE start_timer;
PROCEDURE show_elapsed (str IN VARCHAR2);
END tmr;
/
CREATE OR REPLACE PACKAGE BODY tmr
IS
last_timing NUMBER := NULL;
PROCEDURE start_timer
IS
BEGIN
last_timing := DBMS_UTILITY.get_time;
END;
PROCEDURE show_elapsed (str IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.put_line (
str
|| ': '
|| MOD (DBMS_UTILITY.get_time - last_timing + POWER (2, 32),
POWER (2, 32)));
start_timer;
END;
END tmr;
/
CREATE TABLE not_much_stuff (n NUMBER)
;
INSERT INTO not_much_stuff
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL < 11
;
-- Demonstration of Exception Behavior with SELECT-INTO
DECLARE
my_n not_much_stuff.n%TYPE;
BEGIN
DBMS_OUTPUT.put_line ('No rows found:');
BEGIN
SELECT n
INTO my_n
FROM not_much_stuff
WHERE n = -1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
END;
DBMS_OUTPUT.put_line ('Too many rows found:');
BEGIN
SELECT n
INTO my_n
FROM not_much_stuff
WHERE n BETWEEN 1 AND 10;
EXCEPTION
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
END;
END;
/
DECLARE
my_n not_much_stuff.n%TYPE;
BEGIN
tmr.start_timer;
FOR indx IN 1 .. 10000
LOOP
BEGIN
SELECT n
INTO my_n
FROM not_much_stuff
WHERE n = -1;
my_n := 100;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
my_n := 100;
END;
END LOOP;
DBMS_OUTPUT.put_line (my_n);
tmr.show_elapsed ('Implicit Failure');
END;
/
DECLARE
my_n not_much_stuff.n%TYPE;
BEGIN
tmr.start_timer;
FOR indx IN 1 .. 10000
LOOP
BEGIN
SELECT n
INTO my_n
FROM not_much_stuff
WHERE n = 1;
my_n := 100;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
my_n := 100;
END;
END LOOP;
DBMS_OUTPUT.put_line (my_n);
tmr.show_elapsed ('Implicit Success');
END;
/
DECLARE
my_n not_much_stuff.n%TYPE;
CURSOR stuff_cur
IS
SELECT n
FROM not_much_stuff
WHERE n = -1;
BEGIN
tmr.start_timer;
FOR indx IN 1 .. 10000
LOOP
OPEN stuff_cur;
FETCH stuff_cur INTO my_n;
IF stuff_cur%NOTFOUND
THEN
my_n := 100;
END IF;
CLOSE stuff_cur;
END LOOP;
DBMS_OUTPUT.put_line (my_n);
tmr.show_elapsed ('Explicit Failure');
END;
/
DECLARE
my_n not_much_stuff.n%TYPE;
CURSOR stuff_cur
IS
SELECT n
FROM not_much_stuff
WHERE n = 1;
BEGIN
tmr.start_timer;
FOR indx IN 1 .. 10000
LOOP
OPEN stuff_cur;
FETCH stuff_cur INTO my_n;
IF stuff_cur%FOUND
THEN
my_n := 100;
END IF;
CLOSE stuff_cur;
END LOOP;
DBMS_OUTPUT.put_line (my_n);
tmr.show_elapsed ('Explicit Success');
END;
/
-- 1. Implicit cursor inside a nested block
CREATE OR REPLACE PROCEDURE do_stuff_with_employee (
employee_id_in IN hr.employees.employee_id%TYPE)
IS
l_name hr.employees.last_name%TYPE;
BEGIN
BEGIN
SELECT last_name
INTO l_name
FROM hr.employees e
WHERE e.employee_id = do_stuff_with_employee.employee_id_in;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
/* log the error if this really is an error or let it go... */
l_name := NULL;
END;
IF l_name IS NOT NULL
THEN
/* continue with application logic */
NULL;
END IF;
END;
/
-- 2. Implicit cursor inside a nested subprogram
CREATE OR REPLACE PROCEDURE do_stuff_with_employee (
employee_id_in IN hr.employees.employee_id%TYPE)
IS
l_name hr.employees.last_name%TYPE;
FUNCTION emp_name (employee_id_in IN hr.employees.employee_id%TYPE)
RETURN hr.employees.last_name%TYPE
IS
l_name hr.employees.last_name%TYPE;
BEGIN
SELECT last_name
INTO l_name
FROM hr.employees
WHERE employee_id = employee_id_in;
RETURN l_name;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
/* log the error if this really is an error or let it go... */
RETURN NULL;
END;
BEGIN
l_name := emp_name (employee_id_in);
IF l_name IS NOT NULL
THEN
/* continue with application logic */
NULL;
END IF;
END;
/
-- 3. Explicit cursor unconcerned with too many rows
CREATE OR REPLACE PROCEDURE do_stuff_with_employee (
employee_id_in IN hr.employees.employee_id%TYPE)
IS
l_name hr.employees.last_name%TYPE;
CURSOR name_cur
IS
SELECT last_name
FROM hr.employees e
WHERE e.employee_id = do_stuff_with_employee.employee_id_in;
BEGIN
OPEN name_cur;
FETCH name_cur INTO l_name;
CLOSE name_cur;
IF l_name IS NOT NULL
THEN
/* continue with application logic */
NULL;
END IF;
END;
/
-- 4. Explicit cursor that checks for too many rows
CREATE OR REPLACE PROCEDURE do_stuff_with_employee (
employee_id_in IN hr.employees.employee_id%TYPE)
IS
l_name hr.employees.last_name%TYPE;
l_name2 hr.employees.last_name%TYPE;
CURSOR name_cur
IS
SELECT last_name
FROM hr.employees e
WHERE e.employee_id = do_stuff_with_employee.employee_id_in;
BEGIN
OPEN name_cur;
FETCH name_cur INTO l_name;
FETCH name_cur INTO l_name2;
IF name_cur%FOUND
THEN
CLOSE name_cur;
RAISE TOO_MANY_ROWS;
ELSE
CLOSE name_cur;
END IF;
IF l_name IS NOT NULL
THEN
/* continue with application logic */
NULL;
END IF;
END;
/
答案 1 :(得分:0)
你可以做这些事情:
如果最终插入:
答案 2 :(得分:0)
我必须说出经常用于检查记录是否已存在于数据库中的内容,但是 非常不推荐!这是计算所有行只是为了检查:
fetch (url)
.then(data => data.json()) if needed
.then(data => this.setState(data))
请永远不要使用此!这是编程懒惰的例子!