Skip to main content

Oracle

Oracle 数据库

文档链接:

分片

基础DML

给某一列添加限制:

ALTER TABLE PERFORMANCE_PARTS
MODIFY WEIGHT NOT NULL;

SQL标准

[集合运算符](The Set Operators (oracle.com))

UNION:合并查询结果,去除重复结果、

UNION ALL:合并查询结果,不去除重复结果、

INTERSECT:只取查询结果的交集、

MINUS:只在第一个查询结果,不在第二个结果、

EXCEPT:和MINUS一样

PL/SQL

在PL/SQL中,一个“块”是一个基本单元,由DECLARE, BEGIN, EXCEPTION, END定义。如:

<< label >> (optional)
DECLARE -- Declarative part (optional)
-- Declarations of local types, variables, & subprograms

BEGIN -- Executable part (required)
-- Statements (which can use items declared in declarative part)

[EXCEPTION -- Exception-handling part (optional)
-- Exception handlers for exceptions (errors) raised in executable part]
END;

子程序

一个子程序就是可重复执行的语句块。

除此之外,PL/SQL还可以调用其他语言写的外部子程序。

赋值

DECLARE
valid_id BOOLEAN;
BEGIN
valid_id := TRUE;
END;

SELECT INTO

DECLARE
bonus NUMBER(8,2);
BEGIN
SELECT salary * 0.10 INTO bonus
FROM employees
WHERE employee_id = 100;
END;

DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus));
/

Row Locks

A transaction acquires a row lock for each row modified by one of the following statements: INSERT, UPDATE, DELETE, MERGE, and SELECT ... FOR UPDATE. The row lock exists until the transaction commits or rolls back.

Table Locks

A transaction automatically acquires a table lock (TM lock) when a table is modified with the following statements: INSERT, UPDATE, DELETE, MERGE, and SELECT ... FOR UPDATE. These DML operations require table locks to reserve DML access to the table on behalf of a transaction and to prevent DDL operations that would conflict with the transaction. You can explicitly obtain a table lock using the LOCK TABLE statement, as described in "Manual Data Locking".

SQL StatementRow LocksTable Lock ModeRSRXSSRXX
SELECT ... FROM table...noneYYYYY
INSERT INTO table ...YesSXYYNNN
UPDATE table ...YesSXYFoot 1YFoot 1NNN
MERGE INTO table ...YesSXYYNNN
DELETE FROM table ...YesSXYFoot 1YFoot 1NNN
SELECT ... FROM table FOR UPDATE OF ...YesSXYFoot 1YFoot 1NNN
LOCK TABLE table IN ...
ROW SHARE MODESSYYYYN
ROW EXCLUSIVE MODESXYYNNN
SHARE MODESYNYNN
SHARE ROW EXCLUSIVE MODESSXYNNNN
EXCLUSIVE MODEXNNNNN
查看锁表进程
select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID; 

MERGE INTO

MERGE INTO schema. table alias
USING { schema. table | views | query} alias
ON {(condition) }
WHEN MATCHED THEN
UPDATE SET {clause}
WHEN NOT MATCHED THEN
INSERT VALUES {clause};

INTO 子句 用于指定你所update或者Insert目的表。 USING 子句 用于指定你要update或者Insert的记录的来源,它可能是一个表,视图,子查询。 ON Clause 用于目的表和源表(视图,子查询)的关联,如果匹配(或存在),则更新,否则插入。 merge_update_clause 用于写update语句 merge_insert_clause 用于写insert语句

WHILE...LOOP...END LOOP

DECLARE
done BOOLEAN; -- Initial value is NULL by default
counter NUMBER := 0;
BEGIN
done := FALSE; -- Assign literal value
WHILE done != TRUE -- Compare to literal value
LOOP
counter := counter + 1;
done := (counter > 500); -- Assign value of BOOLEAN expression
END LOOP;
END;
/

字符串连接符 ||

DECLARE
x VARCHAR2(4) := 'suit';
y VARCHAR2(4) := 'case';
BEGIN
DBMS_OUTPUT.PUT_LINE (x || y);
END;
/

输出结果:

suitcase

字符串连接符会无视NULL,如

BEGIN
DBMS_OUTPUT.PUT_LINE ('apple' || NULL || NULL || 'sauce');
END;
/

输出

applesauce

逻辑与或非

xyx AND yx OR yNOT x
TRUETRUETRUETRUEFALSE
TRUEFALSEFALSETRUEFALSE
TRUENULLNULLTRUEFALSE
FALSETRUEFALSETRUETRUE
FALSEFALSEFALSEFALSETRUE
FALSENULLFALSENULLTRUE
NULLTRUENULLTRUENULL
NULLFALSEFALSENULLNULL
NULLNULLNULLNULLNULL

逻辑运算符

OperatorMeaning
=equal to
<>, !=, ~=, ^=not equal to
<less than
>greater than
<=less than or equal to
>=greater than or equal to

几个坑:

TRUE是大于FALSE

字符串比的是二进制

日期,越往后越大

LIKE

下划线_匹配一个字符

百分号%匹配0或多个字符

BETWEEN

BEGIN
print_boolean ('2 BETWEEN 1 AND 3', 2 BETWEEN 1 AND 3);
print_boolean ('2 BETWEEN 2 AND 3', 2 BETWEEN 2 AND 3);
print_boolean ('2 BETWEEN 1 AND 2', 2 BETWEEN 1 AND 2);
print_boolean ('2 BETWEEN 3 AND 4', 2 BETWEEN 3 AND 4);
END;
/

结果

2 BETWEEN 1 AND 3 = TRUE
2 BETWEEN 2 AND 3 = TRUE
2 BETWEEN 1 AND 2 = TRUE
2 BETWEEN 3 AND 4 = FALSE
Data TypeMaximum Size in PL/SQLMaximum Size in SQL
CHAR32,767 bytes2,000 bytes
NCHAR32,767 bytes2,000 bytes
RAW32,767 bytes2,000 bytes
VARCHAR232,767 bytes4,000 bytes
NVARCHAR232,767 bytes4,000 bytes
LONG32,760 bytes2 gigabytes (GB) - 1
LONG RAW32,760 bytes2 GB
BLOB128 terabytes (TB)(4 GB - 1) * database_block_size
CLOB128 TB(4 GB - 1) * database_block_size
NCLOB128 TB(4 GB - 1) * database_block_size

varchar放不下的,可以用clob

Blank-padding

DECLARE
first_name CHAR(10 CHAR);
last_name VARCHAR2(10 CHAR);
BEGIN
first_name := 'John ';
last_name := 'Chen ';

DBMS_OUTPUT.PUT_LINE('*' || first_name || '*');
DBMS_OUTPUT.PUT_LINE('*' || last_name || '*');
END;
/

输出

*John      *
*Chen *

VARCHAR2 不会自动补齐空格,CHAR会给字符串末尾补齐空格。

注释

单行注释

-- Begin processing

多行注释

/*
IF 2 + 2 = 4 THEN
some_condition := TRUE;
/* We expect this THEN to always be performed */
END IF;
*/

Table, Array, 用户自定义类型TYPE

DECLARE
-- Associative array indexed by string:

TYPE population IS TABLE OF NUMBER -- Associative array type
INDEX BY VARCHAR2(64); -- indexed by string

city_population population; -- Associative array variable
i VARCHAR2(64); -- Scalar variable

BEGIN
-- Add elements (key-value pairs) to associative array:

city_population('Smallville') := 2000;
city_population('Midland') := 750000;
city_population('Megalopolis') := 1000000;

-- Change value associated with key 'Smallville':

city_population('Smallville') := 2001;

-- Print associative array:

i := city_population.FIRST; -- Get first element of array

WHILE i IS NOT NULL LOOP
DBMS_Output.PUT_LINE
('Population of ' || i || ' is ' || city_population(i));
i := city_population.NEXT(i); -- Get next element of array
END LOOP;
END;
/

SQL练习

表1: Person

+-------------+---------+ | 列名 | 类型 | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ PersonId 是上表主键

表2: Address

+-------------+---------+ | 列名 | 类型 | +-------------+---------+ | AddressId | int | | PersonId | int | | City | varchar | | State | varchar | +-------------+---------+ AddressId 是上表主键

编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息

FirstName, LastName, City, State

https://leetcode-cn.com/problems/combine-two-tables

标准解法:

select FirstName, LastName, City, State
from Person left join Address
on Person.PersonId = Address.PersonId

左外连接,如果右表没有数据,就为空。