DBMS 中的游标——定义、类型、属性、用途
数据库管理系统 (DBMS) 支持数据操作语言语句,如插入、更新和删除查询。每个数据库在语法上有所不同,但在上述操作中功能保持不变。在本文中,让我们了解如何使用游标执行插入、更新和删除查询。
光标
每当执行 DML 语句时,都会在系统内存中创建一个临时工作区,称为游标。一个游标可以有不止一行,但在处理方面只考虑了 1 行。游标在 Oracle、SQL Server、MySQL 等各种数据库中都非常有用。它们可以很好地与更新、插入和删除等 DML 语句一起使用。特别是隐式游标与这些操作一起存在。它不时更改值,因此需要在局部变量中分配隐式游标属性值以供进一步使用。在 PL/SQL 中,有两种不同类型的游标可用。
- 隐式游标
- 显式游标
显式游标
显式游标由程序员定义,以便在上下文区域拥有更多控制区域。它必须在 PL/SQL 块的声明部分中定义。通常,它在 SELECT 语句中定义,并返回多行作为输出。我们可以遍历数据行并执行所需的操作。
创建显式游标涉及的步骤:
- 初始化内存的光标声明
CURSOR IS
SELECT FROM ;
- 光标打开分配内存
OPEN ;
- 光标获取以检索数据
FETCH INTO
- 光标关闭以释放分配的内存
CLOSE ;
例子:
DECLARE
empId employees.EMPLOYEEID%type;
empName employees.EMPLOYEENAME%type;
empCity employees.EMPLOYEECITY%type;
CURSOR c_employees is
SELECT EMPLOYEEID, EMPLOYEENAME, EMPLOYEECITY FROM employees;
BEGIN
OPEN c_employees;
LOOP
FETCH c_employees into empId , empName , empCity;
EXIT WHEN c_employees %notfound;
dbms_output.put_line(empId || ' ' || empName || ' ' || empCity);
END LOOP;
CLOSE c_employees ;
END;
/
输出:
隐式游标
对于 DML 语句,PL/SQL 中可以使用隐式游标,即无需声明游标,即使对于返回 1 行的查询,也可以使用隐式游标。通过游标属性,我们可以跟踪隐式游标的执行信息。
隐式游标的属性:
隐式游标属性提供有关执行 INSERT、UPDATE 和 DELETE 的结果。我们有不同的光标属性,例如“%FOUND”、“%ISOPEN”、“%NOTFOUND”和 %ROWCOUNT。最近执行的 SQL 语句结果将在 Cursor 中可用。最初,游标值将为空。
让我们一一查看关于 DML 语句的不同游标属性。因此,让我们在 oracle 中创建一个名为“employees”的示例表:
CREATE TABLE employees
( EMPLOYEEID number(10) NOT NULL,
EMPLOYEENAME varchar2(50) NOT NULL,
EMPLOYEECITY varchar2(50)
);
在“employees”表中插入记录
INSERT INTO employees (employeeId,employeeName,employeeCity) VALUES (1,'XXX','CHENNAI');
INSERT INTO employees (employeeId,employeeName,employeeCity) VALUES (2,'XYZ','MUMBAI');
INSERT INTO employees (employeeId,employeeName,employeeCity) VALUES (3,'YYY','CALCUTTA');
“员工”表中存在记录
SELECT * FROM employees;
%FOUND 属性
CREATE TABLE tempory_employee AS SELECT * FROM employees;
DECLARE
employeeNo NUMBER(4) := 2;
BEGIN
DELETE FROM tempory_employee WHERE employeeId = employeeNo ;
IF SQL%FOUND THEN -- delete succeeded
INSERT INTO tempory_employee (employeeId,employeeName,employeeCity) VALUES (2, 'ZZZ', 'Delhi');
END IF;
END;
/
现在检查 tempory_employee 表中的详细信息
SELECT * FROM tempory_employee;
输出:
%FOUND 属性和执行更新操作示例
CREATE TABLE tempory_employee1 AS SELECT * FROM employees;
DECLARE
employeeNo NUMBER(4) := 2;
BEGIN
DELETE FROM tempory_employee WHERE employeeId = employeeNo ;
IF SQL%FOUND THEN -- delete succeeded
UPDATE employees SET employeeCity = 'Chandigarh' WHERE employeeId = 1;
END IF;
END;
/
SELECT * FROM 员工的输出:
更新操作时的 %FOUND 属性,然后执行删除操作示例
CREATE TABLE tempory_employee2 AS SELECT * FROM employees;
DECLARE
employeeNo NUMBER(4) := 2;
BEGIN
UPDATE tempory_employee2 SET employeeCity = 'Gurgaon' WHERE employeeId = employeeNo;
IF SQL%FOUND THEN -- update succeeded
DELETE FROM tempory_employee2 WHERE employeeId = 1 ; -- Then delete a specific row
END IF;
END;
/
输出:
%ISOPEN 属性:对于隐式游标,结果始终为 False。原因是 Oracle 在执行 DML 结果后立即关闭。因此结果为 FALSE。
%NOTFOUND 属性:与 %FOUND 正好相反。 %NOTFOUND 与 %FOUND 在逻辑上相反。 %NOTFOUND 对不影响行的 INSERT、UPDATE 或 DELETE 语句产生 TRUE 值。默认情况下,它返回 False。
%ROWCOUNT 属性:受 INSERT、UPDATE 或 DELETE 语句影响的行数由 %ROWCOUNT 给出。当没有行受到影响时,%ROWCOUNT 给出 0 作为结果,否则返回已删除的行数。
CREATE TABLE tempory_employee3 AS SELECT * FROM employees;
DECLARE employeeNo NUMBER(4) := 2;
BEGIN
DELETE FROM tempory_employee3 WHERE employeeId = employeeNo ;
DBMS_OUTPUT.PUT_LINE('Number of employees deleted: ' || TO_CHAR(SQL%ROWCOUNT));
END;
输出:
游标属性的值必须保存在局部变量中,并且这些变量可以在将来的使用中使用。原因是在不同块中执行多个数据库操作时,游标属性值不断变化,因此这是非常需要的。
%NOTFOUND 属性最好只与 DML 语句一起使用,而不是与 SELECT INTO 语句一起使用。