It. oyksoft. for convenience, compost641 has created the following simple model and constructed some test data: in a business acceptance subsystem BSS, the SQL code-the customer data table createtablecustomers (mermer_idnumber (8) notnull, -- the customer identifies city_namevarchar2 (10) notnull,
Http://it.oyksoft.com/post/641/ for convenience, the following simple model is established and part of the test data is constructed: In a business acceptance subsystem BSS, the SQL code -- customer data table create table customers (customer_id number (8) not null, -- customer ID city_name varchar2 (10) not null,
Http://it.oyksoft.com/post/641/
For convenience, the following simple model is created and some test data is constructed:
In BSS,
SQL code
- -- Customer data table
- Createtable MERs
- (
- Customer_id number (8) notnull, -- customer ID
- City_name varchar2 (10) notnull, -- City
- Customer_type char (2) notnull, -- customer type
- ...
- )
- Createuniqueindex PK_customers on MERs (customer_id)
For some reason, the customer's city information is not accurate,
In the CRM subsystem of the customer service department, 20% of the customers are obtained through the active service
City and other accurate information, so you extract this part of information to a temporary table:
SQL code
- Createtable tmp_cust_city
- (
- Customer_id number (8) notnull,
- Citye_name varchar2 (10) notnull,
- Customer_type char (2) notnull
- )
1) The simplest form
SQL code
- -- It is confirmed that all the mermer_id values in the MERs table are 'beijing' if they are less than 1000'
- -- Less than 1000 of the customers are old customers in the city before the company moved to the whole country :)
- Update MERs
- Set city_name = 'beijing'
- Where customer_id & lt; 1000
2) two tables (multiple tables) join the update -- only join in the where clause
SQL code
- -- The extracted data is VIP and new data is included. Therefore, the customer category is updated by the way.
- Update MERs a -- use an alias
- Set customer_type = '01' -- 01 is vip, 00 is normal
- Where exists (select 1
- From tmp_cust_city B
- Where B. customer_id = a. customer_id
- )
3) two tables (multiple tables) are associated with update. The modified value is calculated from the other table.
SQL code
- Update MERs a -- use an alias
- Set city_name = (select B. city_namefrom tmp_cust_city B where B. customer_id = a. customer_id)
- Where exists (select 1
- From tmp_cust_city B
- Where B. customer_id = a. customer_id
- )
- -- Update has more than 2 values
- Update MERs a -- use an alias
- Set (city_name, customer_type) = (select B. city_name, B. customer_type
- From tmp_cust_city B
- Where B. customer_id = a. customer_id)
- Where exists (select 1
- From tmp_cust_city B
- Where B. customer_id = a. customer_id
- )
Note that in this statement,
= (Select B. city_name, B. customer_typefrom tmp_cust_city B
Where B. customer_id = a. customer_id)
And
(Select 1 from tmp_cust_city B
Where B. customer_id = a. customer_id)
It is two independent subqueries. According to the execution plan, two articles are scanned for table B/index;
If the where condition is discarded, the entire table is created for table A by default.
Update, but because
SQL code
- Select B. city_name from tmp_cust_city B where B. customer_id = a. customer_id
It may not provide "enough" value, because tmp_cust_city is only part of the customer's information, so an error is returned (if the specified column -- city_name can be NULL, it is another question ):
SQL code
- 01407,000 00, "cannot update (% s) to NULL"
- // * Cause:
- // * Action:
An alternative method can be:
SQL code
- Update MERs a -- use an alias
- Set city_name = nvl (select B. city_namefrom tmp_cust_city B where B. customer_id = a. customer_id), a. city_name)
Or
SQL code
- Set city_name = nvl (select B. city_namefrom tmp_cust_city B where B. customer_id = a. customer_id), 'unknown ')
-- Of course this is not in line with the business logic
4) 3) In some cases, because table B records only 20-30% of Table A records,
Considering the use of INDEX in Table A, Using cursor may bring better performance than associating update:
SQL code
- Set serveroutput on
- Declare
- Cursor city_cur is
- Select customer_id, city_name
- From tmp_cust_city
- Orderby customer_id;
- Begin
- For my_cur in city_cur loop
- Update MERs
- Set city_name = my_cur.city_name
- Where customer_id = my_cur.customer_id;
- /** You can submit one or multiple rows to avoid table lock **/
- -- If mod (city_cur % rowcount, 10000) = 0 then
- -- Dbms_output.put_line ('----');
- -- Commit;
- -- End if;
- End loop;
- End;
5) a special case of associated update and further exploration of performance
In oracle's update statement syntax, in addition to the update table, it can also be a view, so there is one special case:
SQL code
- Update (select a. city_name, B. city_nameas new_name
- From MERs,
- Tmp_cust_city B
- Where B. customer_id = a. customer_id
- )
- Set city_name = new_name
This avoids two scans on table B or its indexes, provided that A (customer_id) B (customer_id) must be A unique index or primary key. Otherwise, an error is returned:
SQL code
- 01779,000 00, "cannot modify a column which maps to a non key-preserved table"
- // * Cause: An attempt was made toinsertorupdate columns of ajoinview which
- // Map to a non-key-preservedtable.
- // * Action: Modify the underlying base tables directly.
6) Another common oracle Error
3) For some reason, tmp_cust_city mermer_id is not the unique index/primary key.
SQL code
- Update MERs a -- use an alias
- Set city_name = (select B. city_namefrom tmp_cust_city B where B. customer_id = a. customer_id)
- Where exists (select 1
- From tmp_cust_city B
- Where B. customer_id = a. customer_id
- )
When a given a. mermer_id
(Select B. city_namefrom tmp_cust_city bwhere B. customer_id = a. customer_id)
If one additional entry is returned, the following error is returned:
SQL code
- 01427,000 00, "single-row subquery returns more than one row"
- // * Cause:
- // * Action:
A relatively simple approach that is similar to irresponsible is
SQL code
- Update MERs a -- use an alias
- Set city_name = (select B. city_namefrom tmp_cust_city B where B. customer_id = a. customer_idand rownum = 1)
How to Understand the 01427 error. In a complicated multi-table join update statement, this error is often caused by weeks of consideration,
The preceding example is still described. A simple method is to import Table A into the value expression using group by and
Having statement to view Repeated Records
SQL code
- (Select B. customer_id, B. city_name, count (*)
- From tmp_cust_city B, MERS MERs
- Where B. customer_id = a. customer_id
- Groupby B. customer_id, B. city_name
- Havingcount (*)> = 2
- )