Làm cách nào để di chuyển các thủ tục lưu trữ SQL Server bằng cách sử dụng các bảng tạm thời hoặc các biến bảng vào Oracle?


9

Nhà phát triển C # được ban quản lý khuyến khích viết các thủ tục lưu trữ SQL Server thường tạo ra các thủ tục như thế này

create table #t1 (...);
insert into #t1 Select ... from table_a where ...;
insert into #t1 Select ... from table_b where ...;
update #t1 Set ... = ... where ...
Select * from #t1;

Câu lệnh đơn khá đơn giản và phương pháp này làm cho chúng tạo ra kết quả chính xác.

Thường thì nhiệm vụ của tôi là di chuyển các thủ tục như vậy sang Oracle.

Hãy đối mặt với sự thật sau đây.

  • Để các bảng tạm thời khác nhau trong SQL Server hoàn toàn độc lập và có thể có bất kỳ cấu trúc ad hoc nào.
  • Các bảng chung toàn cầu của Oracle là các đối tượng toàn cầu và tất cả đều sử dụng nhiều chia sẻ cùng một cấu trúc bảng. Sửa đổi cấu trúc này là không thể, trong khi nó được sử dụng ở bất cứ đâu.

Một trong những điều tôi học được từ một dba của Oracle, là tránh sử dụng các bảng tạm thời bất cứ khi nào có thể. Ngay cả hiệu suất trên máy chủ SQL cũng được hưởng lợi từ các sửa đổi như vậy.

Thay thế các phần chèn riêng lẻ bằng các công đoàn

Trong trường hợp đơn giản nhất, ở trên có thể được chuyển đổi thành một cái gì đó như

select case when ... then ... end, ... from table_a where ...
union
select case when ... then ... end, ... from table_b where ...
Order by ...;

Sử dụng các chức năng

Cả hai hàm vô hướng và các hàm có giá trị bảng có thể giúp chuyển đổi thủ tục của bạn thành một truy vấn duy nhất của biểu mẫu trên.

Biểu thức bảng chung aka Bao thanh toán phụ

Subquery Factoring gần như là thứ tốt nhất mà Oracle cung cấp để tránh các bảng tạm thời. Sử dụng nó, việc di chuyển SQL Server sang Oracle một lần nữa khá dễ dàng. Điều này đòi hỏi SQL Server 2005 trở lên.


Những sửa đổi này cải thiện phiên bản SQL Server và trong nhiều trường hợp làm cho việc di chuyển thẳng tiến. Trong các trường hợp khác, sử dụng các bảng tạm thời toàn cầu để có thể thực hiện di chuyển trong thời gian giới hạn, nhưng nó ít thỏa mãn hơn.


Có cách nào khác để tránh việc sử dụng các bảng tạm thời toàn cầu trong Oracle không?


3
Tôi sẽ nói rằng mã như thế là biểu thị của tư duy dựa trên thủ tục không được thiết lập. Và đây là các bảng tạm thời cục bộ với một # duy nhất. Tôi là quản lý và tôi sẽ bị gãy chân nếu tôi thấy điều đó sẽ được đưa vào sản xuất :-)
gbn

Tôi hoàn toàn đồng ý
bernd_k

@gbn - PL / SQL thành ngữ có xu hướng thủ tục hơn một chút so với T-SQL thành ngữ. Các bảng tạm thời cho phép thực hiện gần như mọi thứ trong tập hợp ops trong T-SQL. PL / SQL có ops con trỏ song song và nhiều chức năng hơn để tối ưu hóa mã thủ tục.
Mối quan tâmOfTunbridgeWells

Câu trả lời:


3

Một cách để làm điều này sẽ là Các loại đối tượng , trong trường hợp này, loại này sẽ gây khó chịu cho bạn #t1. Vì vậy, nó sẽ cần được xác định ở đâu đó nhưng nó không cần phải là toàn cục, nó có thể là mỗi lược đồ hoặc mỗi thủ tục. Đầu tiên, chúng ta có thể tạo một loại:

SQL> create or replace type t1_type as object (x int, y int, z int)
  2  /

Type created.

SQL> create or replace type t1 as table of t1_type
  2  /

Type created.

Bây giờ thiết lập một số dữ liệu mẫu:

SQL> create table xy (x int, y int)
  2  /

Table created.

SQL> insert into xy values (1, 2)
  2  /

1 row created.

SQL> insert into xy values (3, 4)
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

Và tạo một hàm trên dữ liệu này trả về loại "tạm thời" của chúng tôi:

SQL> create or replace function fn_t1 return t1 as
  2  v_t1 t1 := t1();       -- empty temporary table (really an array)
  3  v_ix number default 0; -- array index
  4  begin
  5  for r in (select * from xy) loop
  6  v_ix := v_ix + 1;
  7  v_t1.extend;
  8  v_t1(v_ix) := t1_type(r.x, r.y, (r.x + r.y));
  9  end loop;
 10  return v_t1;
 11  end;
 12  /

Function created.

Và cuối cùng:

SQL> select * from the (select cast (fn_t1 as t1) from dual)
  2  /

         X          Y          Z
---------- ---------- ----------
         1          2          3
         3          4          7

Như bạn có thể thấy điều này khá khó hiểu (và sử dụng các hàm giả bộ sưu tập , đây là một tính năng tối nghĩa!), Như tôi luôn nói, chuyển từ DB sang DB không chỉ đơn thuần là về cú pháp và từ khóa trong phương ngữ SQL của chúng , khó khăn thực sự đến từ các giả định cơ bản khác nhau (trong trường hợp SQL Server, rằng các con trỏ đắt tiền và việc sử dụng chúng tránh / làm việc xung quanh bằng mọi giá).


3

Nếu tùy chọn trường hợp không đủ linh hoạt, bạn có thể thu thập dữ liệu hàng loạt trong quy trình của mình và thao tác với (các) mảng.

--Setup
CREATE TABLE table_a (c1 Number(2));
CREATE TABLE table_b (c1 Number(2));
INSERT INTO table_a (SELECT rownum FROM dual CONNECT BY rownum<=4);
INSERT INTO table_b (SELECT rownum+5 FROM dual CONNECT BY rownum<=4);

--Example
DECLARE
   Type tNumberArray Is Table Of Number;
   v1 tNumberArray;
BEGIN
   SELECT c1 BULK COLLECT INTO v1 FROM (
      SELECT c1 FROM table_a
      UNION ALL
      SELECT c1 FROM table_b
      );

   For x IN v1.First..v1.Last Loop
      /* Complex manipulation goes here. */
      If (v1(x) <= 3) Then
         v1(x) := v1(x)*10;
      End If;
      DBMS_OUTPUT.PUT_LINE(v1(x));
   End Loop;
END;
/

+1, nhưng điều này không trả về tập kết quả (nếu a SELECTlà điều cuối cùng trong gói lưu trữ T-SQL, đó là những gì nó trả về)
Gaius

Nếu khối mã này được biến thành một thủ tục, bạn có thể trả về mảng hoặc mở các mảng dưới dạng con trỏ và đưa con trỏ trở lại, hoặc thậm chí biến nó thành hàm và đặt lại các hàng. Mỗi cái sẽ tương tự nhau, nhưng cái bạn nên sử dụng sẽ phụ thuộc vào tình huống.
Leigh Riffel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.