

 Amazon Redshift 將不再支援從修補程式 198 開始建立新的 Python UDFs。現有 Python UDF 將繼續正常運作至 2026 年 6 月 30 日。如需詳細資訊，請參閱[部落格文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# DECLARE
<a name="declare"></a>

定義新的資料指標。使用資料指標可從完整查詢的結果集中一次擷取幾個資料列。

擷取資料指標的第一列時，整個結果集會在領導節點上、記憶體中或磁碟上具體化 (如有需要)。由於在大型結果集內使用資料指標可能會對效能造成負面影響，因此建議您盡量使用替代方式。如需詳細資訊，請參閱[使用游標時的效能考量](#declare-performance)。

您必須在交易區塊內宣告資料指標。每個工作階段中一次只能開啟一個資料指標。

如需詳細資訊，請參閱 [FETCH](fetch.md)、[CLOSE](close.md)。

## 語法
<a name="declare-synopsis"></a>

```
DECLARE cursor_name CURSOR FOR query
```

## Parameters
<a name="declare-parameters"></a>

*cursor\$1name*   
新資料指標的名稱。

 *query*   
填入資料指標的 SELECT 陳述式。

## DECLARE CURSOR 使用須知
<a name="declare-usage"></a>

若您的用戶端應用程式使用 ODBC 連線，且您的查詢建立的結果集太大，無法納入記憶體中，則您可以使用資料指標將結果集串流到用戶端應用程式。當您使用資料指標時，整個結果集會在領導節點上具體化，然後您的用戶端就能以遞增方式擷取結果。

**注意**  
若要在 Microsoft Windows 的 ODBC 中啟用資料指標，請在您用於 Amazon Redshift 的 ODBC DSN 中啟用**使用宣告/擷取**選項。建議您使用 ODBC DSN 選項對話方塊中的 **Cache Size (快取大小)** 欄位，將多節點叢集上的 ODBC 快取大小設定為 4,000 或更大的數字，以減少往返次數。在單一節點叢集上，將 Cache Size (快取大小) 設定為 1,000。

由於使用資料指標可能會對效能造成負面影響，因此建議您盡量使用替代方式。如需詳細資訊，請參閱[使用游標時的效能考量](#declare-performance)。

在滿足以下限制的情況下，可支援 Amazon Redshift 資料指標：
+ 每個工作階段中一次只能開啟一個資料指標。
+ 資料指標必須在交易內使用 (BEGIN … END)。
+ 所有資料指標累積的結果集大小上限受限於叢集節點類型。若您需要更大的結果集，可將大小調整為 XL 或 8XL 節點組態。

  如需詳細資訊，請參閱[游標限制條件](#declare-constraints)。

## 游標限制條件
<a name="declare-constraints"></a>

擷取資料指標的第一列時，整個結果集會在領導節點上具體化。若結果集無法納入記憶體內，則會視需要寫入磁碟中。為保護領導節點的完整性，Amazon Redshift 會根據叢集的節點類型對所有資料指標結果集的大小強制執行限制條件。

下表說明每個叢集節點類型的結果集大小總計上限。結果集大小上限的單位是 MB。


| Node type | 每個叢集的結果集上限 (MB) | 
| --- | --- | 
|   DC2 Large 多個節點   | 192，000 | 
|   DC2 Large 單節點   | 8,000 | 
|   DC2 8XL 多個節點   | 3，200，000 | 
|   RA3 16XL 多個節點   | 14，400，000 | 
|   RA3 4XL 多個節點   | 3，200，000 | 
|   RA3 XLPLUS 多個節點   | 1,000,000 | 
|   RA3 XLPLUS 單節點   | 64，000 | 
|   RA3 LARGE 多個節點   | 240，000 | 
|   RA3 LARGE 單一節點   | 8,000 | 
| Amazon Redshift Serverless | 150，000 | 

若要檢視叢集的使用中資料指標組態，請以超級使用者身分查詢 [STV\$1CURSOR\$1CONFIGURATION](r_STV_CURSOR_CONFIGURATION.md) 系統資料表。若要檢視使用中資料指標的狀態，請查詢 [STV\$1ACTIVE\$1CURSORS](r_STV_ACTIVE_CURSORS.md) 系統資料表。使用者只能看見自己擁有之資料指標的資料列，但超級使用者可檢視所有資料指標。

## 使用游標時的效能考量
<a name="declare-performance"></a>

由於資料指標會在開始傳回結果至用戶端之前，於領導節點上將整個結果集具體化，因此在非常大型的結果集內使用資料指標會對效能產生負面影響。強烈建議您不要在非常大型的結果集內使用資料指標。在某些情況下，例如應用程式使用 ODBC 連線時，資料指標可能會是唯一可行的解決方案。不過我們建議您盡量使用以下替代方式：
+ 使用 [UNLOAD](r_UNLOAD.md) 匯出大型資料表。使用 UNLOAD 時，運算節點會平行運作，將資料直接傳輸至 Amazon Simple Storage Service 上的資料檔案。如需詳細資訊，請參閱[在 Amazon Redshift 中卸載資料](c_unloading_data.md)。
+ 在您的用戶端應用程式中設定 JDBC 擷取大小參數。若您使用 JDBC 連線且發生用戶端記憶體不足的錯誤，您可以藉由設定 JDBC 擷取大小參數，讓用戶端分小批擷取結果集。如需詳細資訊，請參閱[設定 JDBC 擷取大小參數](set-the-JDBC-fetch-size-parameter.md)。

## DECLARE CURSOR 範例
<a name="declare-example"></a>

以下範例會宣告名為 LOLLAPALOOZA 的資料指標來選取 Lollapalooza 活動的銷售資訊，然後使用資料指標從結果集擷取資料列：

```
-- Begin a transaction

begin;

-- Declare a cursor

declare lollapalooza cursor for
select eventname, starttime, pricepaid/qtysold as costperticket, qtysold
from sales, event
where sales.eventid = event.eventid
and eventname='Lollapalooza';

-- Fetch the first 5 rows in the cursor lollapalooza:

fetch forward 5 from lollapalooza;

  eventname   |      starttime      | costperticket | qtysold
--------------+---------------------+---------------+---------
 Lollapalooza | 2008-05-01 19:00:00 |   92.00000000 |       3
 Lollapalooza | 2008-11-15 15:00:00 |  222.00000000 |       2
 Lollapalooza | 2008-04-17 15:00:00 |  239.00000000 |       3
 Lollapalooza | 2008-04-17 15:00:00 |  239.00000000 |       4
 Lollapalooza | 2008-04-17 15:00:00 |  239.00000000 |       1
(5 rows)

-- Fetch the next row:

fetch next from lollapalooza;

  eventname   |      starttime      | costperticket | qtysold
--------------+---------------------+---------------+---------
 Lollapalooza | 2008-10-06 14:00:00 |  114.00000000 |       2

-- Close the cursor and end the transaction:

close lollapalooza;
commit;
```

下列範例會使用資料表中的所有結果在參考游標上循環：

```
CREATE TABLE tbl_1 (a int, b int);
INSERT INTO tbl_1 values (1, 2),(3, 4);

CREATE OR REPLACE PROCEDURE sp_cursor_loop() AS $$
DECLARE
    target record;
    curs1 cursor for select * from tbl_1;
BEGIN
    OPEN curs1;
    LOOP
        fetch curs1 into target;
        exit when not found;
        RAISE INFO 'a %', target.a;
    END LOOP;
    CLOSE curs1;
END;
$$ LANGUAGE plpgsql;

CALL sp_cursor_loop();
         
SELECT message 
   from svl_stored_proc_messages 
   where querytxt like 'CALL sp_cursor_loop()%';
         
  message
----------
      a 1
      a 3
```