2009-06-16 79 views
6

Oracle cho phép bạn cập nhật kết quả của câu lệnh SELECT.Cập nhật kết quả của câu lệnh SELECT

UPDATE (<SELECT Statement>) 
SET <column_name> = <value> 
WHERE <column_name> <condition> <value>; 

Tôi cho rằng điều này có thể được sử dụng để cập nhật các cột trong một bảng dựa trên giá trị của hàng phù hợp trong bảng khác.

Tính năng này được gọi như thế nào, nó có thể được sử dụng hiệu quả cho các bản cập nhật lớn không, nó có hoạt động khi SELECT kết hợp nhiều bảng, và nếu có, làm thế nào?

+2

Có một ví dụ về bản cập nhật tham gia vào một SO khác: http://stackoverflow.com/questions/975315/what-is-wrong-with-my-update-statement-with-a-join-in- oracle/975674 # 975674 - Về hiệu quả: nó có lẽ là cách hiệu quả nhất để cập nhật một tập hợp các hàng –

+1

Nó thường được gọi là xem cập nhật. –

Trả lời

1

Cảm ơn ý kiến, tôi nghĩ rằng đây là tiêu chuẩn Sql ... :(

Đối với Oracle bạn có thể viết một bản cập nhật trên một chiếc bàn nơi bạn lấy thông tin với một tham gia như:

UPDATE (
    SELECT * 
    FROM table1 t1 
    LEFT JOIN table2 t2 ON t2.t1id = t1.ID 
) SET t1.col1 = t2.col2 

Đối sql server, đó là:

UPDATE t1 
SET col1 = t2.col2 
FROM table1 t1 
LEFT JOIN table2 t2 on t2.t1id = t1.id 

Nếu có ai biết một cách để làm điều này mà làm việc trên Oracle, sQL server và MySQL tôi muốn được quan tâm

.
+1

Bạn có chắc chắn rằng các công trình? Trong Oracle, tôi nhận được "ORA-00933: Lệnh SQL không được kết thúc đúng" tại "FROM"? – Thilo

+0

Sử dụng http://www.dpriver.com/pp/sqlformat.htm có vẻ như hoạt động với MSSQL, nhưng cung cấp các lỗi cú pháp cho Oracle, MySQL hoặc DB2 – Thilo

+0

-1 Không có nó không hoạt động trong Oracle. Tôi không chắc đó là SQL chuẩn hay không. –

1

Biểu mẫu bạn đề cập không có tên cụ thể AFAIK. Chỉ cần cập nhật kết quả của câu lệnh chọn.

Có một mẫu gọi là tương quan cập nhật (với bản cập nhật đơn hoặc multicolumn)

UPDATE TABLE(<SELECT STATEMENT>) <alias> 
SET <column_name> = (
    SELECT <column_name> 
    FROM <table_name> <alias> 
    WHERE <alias.table_name> <condition> <alias.table_name> 
); 

Dạng multicolumn

... 
SET (<column_name_list>) = (
    SELECT <column_name_list> 
... 

Ngoài ra còn có một từ đó cũng trở về các giá trị gọi là Cập nhật với mệnh đề trả về

Và một số cụ thể s cho các cập nhật với các bảng lồng nhau. Tốt nhất là để kiểm tra ít nhất này hai trang

Oracle® Database SQL Language Reference SELECT

Oracle® Database SQL Language Reference UPDATE

4

Tôi đã không nhìn thấy một tên chính thức cho việc này. Oracle SQL Reference chỉ đề cập đến việc cập nhật truy vấn phụ. Tôi có xu hướng nghĩ về nó như một hình thức "xem cập nhật", với truy vấn con đang ở chế độ xem trực tuyến.

Có, nó hoạt động khi một số bàn được nối, nhưng phải tuân theo các quy tắc của chế độ xem đang được cập nhật. Điều này có nghĩa là chỉ một trong các bảng cơ sở của chế độ xem có thể được cập nhật và bảng này phải được "giữ nguyên khóa" trong chế độ xem: tức là các hàng của bảng chỉ có thể xuất hiện một lần trong chế độ xem. Điều này đòi hỏi rằng bất kỳ bảng nào khác trong khung nhìn (truy vấn phụ) được tham chiếu thông qua các ràng buộc khóa ngoài trên bảng được cập nhật.

Một số ví dụ có thể hữu ích. Sử dụng các bảng Oracle EMP và DEPT tiêu chuẩn, với EMP.EMPNO được định nghĩa là khóa chính của EMP và EMP.DEPTNO được định nghĩa là khóa ngoài cho DEPT.DEPTNO, sau đó bản cập nhật này được phép:

update (select emp.empno, emp.ename, emp.sal, dept.dname 
     from emp join dept on dept.deptno = emp.deptno 
     ) 
set sal = sal+100; 

Nhưng đây không phải là:

-- DEPT is not "key-preserved" - same DEPT row may appear 
-- several times in view 
update (select emp.ename, emp.sal, dept.deptno, dept.dname 
     from emp join dept on dept.deptno = emp.deptno 
     ) 
set dname = upper(dname); 

Đối với hiệu suất: optimizer sẽ (phải) xác định các bảng cơ sở phải được cập nhật trong thời gian phân tích, và tham gia vào bảng khác sẽ bị bỏ qua vì chúng không có bất kỳ vòng bi nào trên bản cập nhật được thực hiện - vì đầu ra AUTOTRACE này hiển thị:

SQL> update (select emp.ename, emp.sal, dept.dname 
    2    from emp join dept on dept.deptno = emp.deptno 
    3   ) 
    4  set sal = sal-1; 

33 rows updated. 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1507993178 

------------------------------------------------------------------------------------ 
| Id | Operation   | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------ 
| 0 | UPDATE STATEMENT |    | 33 | 495 |  3 (0)| 00:00:01 | 
| 1 | UPDATE    | EMP   |  |  |   |   | 
| 2 | NESTED LOOPS  |    | 33 | 495 |  3 (0)| 00:00:01 | 
| 3 | TABLE ACCESS FULL| EMP   | 33 | 396 |  3 (0)| 00:00:01 | 
|* 4 | INDEX UNIQUE SCAN| SYS_C0010666 |  1 |  3 |  0 (0)| 00:00:01 | 
------------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO") 

(Lưu ý rằng bảng DEPT không bao giờ được truy cập mặc dù DEPT.DNAME appe ars trong truy vấn con).

Các vấn đề liên quan