All Products
Search
Document Center

MaxCompute:Script mode SQL

Last Updated:Jun 21, 2026

Script mode (Script Mode SQL) memungkinkan Anda mengompilasi dan mengirimkan beberapa pernyataan SQL sebagai satu kesatuan. Proses ini menghasilkan satu rencana eksekusi, mengantri skrip sekali, dan menjalankan semua pernyataan dalam satu pekerjaan. Pendekatan ini ideal untuk pipa data ETL, pemrosesan batch periodik, dan skenario orkestrasi kueri yang memerlukan beberapa pernyataan terkoordinasi. Script mode mendukung dua mode eksekusi: mode normal, yang secara default menyediakan eksekusi atomik, dan mode eksekusi langkah demi langkah, yang menjalankan pernyataan secara serial.

  • Script mode tidak mendukung estimasi biaya. Biaya aktual didasarkan pada detail penagihan Anda.

  • Satu skrip dapat mereferensikan hingga 10.000 tabel. Setiap referensi dihitung secara individual, termasuk referensi berulang ke tabel yang sama dan tabel yang direferensikan dalam definisi tampilan.

  • Jika persiapan data untuk beberapa sumber data selesai pada waktu yang sangat berbeda—misalnya, satu pukul 01.00 dan yang lain pukul 07.00—jangan gunakan variabel tabel untuk menggabungkannya menjadi satu pekerjaan Script Mode SQL.

Kasus penggunaan

  • Tulis ulang pernyataan kompleks: Pecah subkueri bersarang menjadi rangkaian penugasan variabel tabel yang mudah dibaca.

  • Buat pipeline multi-pernyataan: Gabungkan pernyataan yang saling terkait secara logis menjadi satu pekerjaan untuk mengurangi overhead antrian dan penjadwalan. Dalam mode normal, semua pernyataan dieksekusi secara atomik. Dalam mode eksekusi langkah demi langkah, pernyataan dijalankan secara serial, yang ideal untuk skenario read-after-write atau migrasi dari platform lain. Untuk informasi lebih lanjut, lihat Mode eksekusi.

Sintaksis

  • Jenis pernyataan: Script mode mendukung pernyataan SET, beberapa pernyataan DDL, dan pernyataan DML. Pernyataan yang menampilkan hasil seperti DESC dan SHOW tidak didukung.

  • Urutan pernyataan: Skrip harus mengikuti urutan tetap SETDDLDML. Setiap bagian dapat berisi nol atau lebih pernyataan, tetapi Anda tidak boleh mencampur pernyataan dari bagian yang berbeda.

-- 1. SET
SET odps.sql.type.system.odps2=true;
[SET odps.stage.reducer.num=xxx;]
[SET odps.sql.step.script.mode=true;] -- Aktifkan mode eksekusi langkah demi langkah
[...]
-- 2. DDL
CREATE TABLE table1 xxx;
[CREATE TEMPORARY TABLE table2 xxx;] -- Buat tabel temporary
[...]
-- 3. DML&DQL
@var1 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
        FROM table3
        [WHERE where_condition];
@var2 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
        FROM table4
        [WHERE where_condition];
@var3 := SELECT [ALL | DISTINCT] var1.select_expr, var2.select_expr, ...
        FROM @var1 JOIN @var2 ON ...;
INSERT OVERWRITE|INTO TABLE [PARTITION (partcol1=val1, partcol2=val2 ...)]
        SELECT [ALL | DISTINCT] select_expr, select_expr, ...
        FROM @var3;    
[@var4 := SELECT [ALL | DISTINCT] var1.select_expr, var1.select_expr, ... FROM @var1 
        UNION ALL | UNION 
        SELECT [ALL | DISTINCT] var2.select_expr, var2.select_expr, ... FROM @var2;    
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name 
        AS 
        SELECT [ALL | DISTINCT] select_expr, select_expr, ...
        FROM @var4;]
[...]

Mode eksekusi

Script mode mendukung dua mode eksekusi.

Perilaku

Normal Mode (default)

Mode eksekusi langkah demi langkah

Cara mengaktifkan

Default. Tidak diperlukan konfigurasi.

Tambahkan SET odps.sql.step.script.mode=true; ke bagian SET.

Kompilasi

Semua pernyataan DML dikompilasi menjadi satu rencana eksekusi.

Setiap pernyataan DML dikompilasi menjadi rencana eksekusi terpisah. Catatan: Skrip yang sangat kompleks, seperti yang memiliki ribuan baris atau banyak operasi, mungkin melebihi batas memori kompilasi.

Eksekusi

Semua pernyataan dieksekusi secara atomik sebagai satu pekerjaan yang hanya dimulai setelah semua data masukan siap. Jika ada pernyataan yang gagal, seluruh skrip gagal dan semua operasi di-rollback.

Pernyataan DML dieksekusi secara serial. Jika suatu pernyataan gagal, pernyataan yang telah dieksekusi sebelumnya tidak di-rollback, dan Anda harus menjalankan ulang skrip dari awal. Kami menyarankan agar Anda membagi skrip besar menjadi skrip yang lebih kecil.

Read-after-write

Tidak didukung. Terjadi error jika Anda menulis ke lalu membaca dari tabel yang sama dalam satu skrip.

Didukung, tetapi tidak untuk tabel transaksional atau tabel partisi.

Tabel temporary

Tidak didukung.

Didukung.

Sintaksis DDL

Buat tabel temporary

Dalam script mode, Anda dapat membuat tabel temporary untuk menyimpan cache hasil antara agar dapat digunakan kembali dalam skrip yang sama. Operasi ini memerlukan pola read-after-write dan hanya didukung dalam mode eksekusi langkah demi langkah.

Sintaksis

CREATE TEMPORARY TABLE <table_name> (
  <col_name> <data_type>, ...
)
[LIFECYCLE <days>]
[AS <select_statement>];

Parameter

Parameter

Deskripsi

table_name

Hanya dapat diakses dalam skrip saat ini.

LIFECYCLE <days>

Opsional. Jumlah hari untuk menyimpan tabel sebelum dihapus secara otomatis. Default: 1.

AS <select_statement>

Opsional. Mengisi tabel dengan data dari pernyataan SELECT saat dibuat.

Batasan

  • Tabel temporary memerlukan mode eksekusi langkah demi langkah. Tambahkan SET odps.sql.step.script.mode=true; ke bagian SET skrip Anda.

  • Tabel temporary hanya dapat diakses dalam skrip tempat tabel tersebut dibuat.

  • Tabel temporary tidak dapat berupa tabel partisi atau tabel transaksional.

  • Untuk menghapus eksplisit tabel temporary, pernyataan DROP TABLE harus menjadi pernyataan terakhir dalam skrip.

  • Hindari membuat lebih dari 20 tabel temporary dalam satu skrip.

Buat tabel standar

Script mode mendukung pembuatan tabel standar. Untuk detail sintaksis, lihat CREATE TABLE.

Sintaksis DML dan DQL

Batasan pernyataan

  • Pernyataan yang menampilkan hasil: Skrip hanya boleh berisi satu pernyataan yang menghasilkan output layar, seperti pernyataan SELECT mandiri. Memasukkan lebih dari satu akan menyebabkan error. Hindari penggunaan jenis pernyataan ini dalam skrip.

  • CREATE TABLE AS: Anda hanya dapat menggunakan pernyataan ini sekali per skrip, dan harus menjadi pernyataan eksekusi terakhir. Kami menyarankan membuat tabel terlebih dahulu lalu memasukkan data.

  • Mode tulis campuran: Anda tidak dapat menggunakan OVERWRITE dan INTO pada tabel yang sama dalam satu skrip. Operasi DML pada tabel transaksional dan tabel standar tidak boleh dicampur.

  • read-after-write: Dalam mode normal, menulis ke lalu membaca dari tabel dalam skrip yang sama menyebabkan error. Untuk mengatasi masalah ini, gunakan variabel tabel atau beralih ke mode eksekusi langkah demi langkah. Mode eksekusi langkah demi langkah mendukung operasi read-after-write, tetapi tidak untuk tabel transaksional atau tabel partisi. Untuk contoh lengkap, lihat Contoh 3: Read-after-write dalam mode normal.

Variabel

Sintaksis

-- Deklarasikan variabel dengan menggunakan @. Jenis yang didukung meliputi TABLE dan semua tipe data MaxCompute.
@var1 <type>
-- Tetapkan nilai dengan menggunakan :=
@var1 := <select_statement>

Catatan penggunaan

  • Anda tidak dapat menetapkan variabel bertipe tabel ke variabel dengan tipe data tertentu. Misalnya, sintaksis berikut tidak diizinkan:

    @a TABLE (name STRING);
    @a := SELECT 'tom';
    @b STRING;
    @b := SELECT * FROM @a;
  • Variabel dapat menyimpan nilai konstan. Anda dapat mengonversi nilai variabel menjadi skalar dengan menggunakan SELECT * FROM @var. Konstanta juga dapat disimpan dalam tabel satu baris, seperti pada contoh berikut. Untuk informasi lebih lanjut tentang sintaksis konversi, lihat subkueri.

    @a := SELECT 10;                                         -- Tetapkan konstanta 10
    @b := SELECT key, value + (SELECT * FROM @a) FROM t2;   -- Gunakan @a sebagai skalar
    SELECT * FROM @b;

Pernyataan IF

Dalam script mode, gunakan pernyataan IF untuk mengontrol alur eksekusi berdasarkan kondisi.

Sintaksis

-- Cabang tunggal
IF (condition) BEGIN
  statements
END
-- Cabang ganda
IF (condition) BEGIN
  statements
END ELSE IF (condition2) BEGIN
  statements
END ELSE BEGIN
  statements
END

Catatan penggunaan

  • Jika cabang hanya berisi satu pernyataan, kata kunci BEGIN dan END bersifat opsional, mirip dengan { } di Java.

  • Pernyataan DDL seperti CREATE TABLE, ALTER TABLE, dan TRUNCATE TABLE tidak didukung dalam cabang IF.

  • Kondisi mendukung dua jenis:

    • Ekspresi Boolean: Cabang ditentukan pada waktu kompilasi.

    • Subkueri skalar Boolean: Cabang ditentukan pada waktu eksekusi. MaxCompute mungkin mengirimkan beberapa pekerjaan.

Contoh 1: Dalam pernyataan IF, kondisinya adalah ekspresi bertipe BOOLEAN. Jenis pernyataan IF ELSE ini dapat menentukan cabang mana yang dieksekusi pada waktu kompilasi, seperti pada contoh berikut:

@date := '20190101';
@row TABLE(id STRING);
IF (CAST(@date AS BIGINT) % 2 == 0) BEGIN
  @row := SELECT id FROM src1;
END ELSE BEGIN
  @row := SELECT id FROM src2;
END
INSERT OVERWRITE TABLE dest SELECT * FROM @row;

Contoh 2: Kondisi dalam pernyataan IF adalah subkueri skalar Boolean. Untuk jenis pernyataan IF ELSE ini, cabang eksekusi ditentukan pada waktu eksekusi, yang mengharuskan MaxCompute mengirimkan beberapa pekerjaan:

@i BIGINT;
@t TABLE(id BIGINT, value BIGINT);
IF ((SELECT COUNT(*) FROM src WHERE a = '5') > 1) BEGIN
  @i := 1;
  @t := SELECT @i, @i*2;
END ELSE BEGIN
  @i := 2;
  @t := SELECT @i, @i*2;
END
SELECT id, value FROM @t;

Contoh

Contoh 1: Contoh dasar

Skrip berikut melakukan join dan union data dari tiga tabel sumber, lalu memasukkan hasilnya ke dua tabel tujuan. Semua pernyataan dikompilasi menjadi satu DAG dan dieksekusi secara atomik.

CREATE TABLE IF NOT EXISTS dest(key STRING, value BIGINT) PARTITIONED BY (d STRING);
CREATE TABLE IF NOT EXISTS dest2(key STRING, value BIGINT) PARTITIONED BY (d STRING);
@a := SELECT * FROM src  WHERE value > 0;
@b := SELECT * FROM src2 WHERE key IS NOT NULL;
@c := SELECT * FROM src3 WHERE value IS NOT NULL;
@d := SELECT a.key, b.value FROM @a LEFT OUTER JOIN @b ON a.key = b.key AND b.value > 0;
@e := SELECT a.key, c.value FROM @a INNER JOIN @c ON a.key = c.key;
@f := SELECT * FROM @d UNION SELECT * FROM @e UNION SELECT * FROM @a;
INSERT OVERWRITE TABLE dest  PARTITION (d='20171111') SELECT * FROM @f;
@g := SELECT e.key, c.value FROM @e JOIN @c ON e.key = c.key;
INSERT OVERWRITE TABLE dest2 PARTITION (d='20171111') SELECT * FROM @g;

Contoh 2: Read-after-write dalam mode langkah demi langkah

Skrip berikut mengaktifkan mode eksekusi langkah demi langkah untuk melakukan operasi read-after-write dalam skrip yang sama.

SET odps.sql.step.script.mode=true;
DROP TABLE IF EXISTS foo_t1;
DROP TABLE IF EXISTS foo_t2;
CREATE TABLE foo_t1(a STRING) LIFECYCLE 1;
CREATE TABLE foo_t2(a STRING) LIFECYCLE 1;
@x := SELECT 'hello, world' AS a;
INSERT OVERWRITE TABLE foo_t1 SELECT * FROM @x;
INSERT INTO foo_t2 SELECT * FROM foo_t1 UNION ALL SELECT * FROM foo_t1;
SELECT * FROM foo_t2;

Contoh 3: Read-after-write dalam mode normal

Dalam mode normal, menulis ke lalu membaca dari tabel yang sama dalam skrip menyebabkan error. Contoh ini menunjukkan error tersebut dan dua solusi yang mungkin.

Persiapan data

CREATE TABLE src(key BIGINT, value BIGINT) LIFECYCLE 1;
CREATE TABLE src2(key BIGINT, value BIGINT) LIFECYCLE 1;
INSERT INTO src VALUES(1, 2), (3, 3);

Contoh error (read-after-write dalam mode normal)

INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0;
@a := SELECT * FROM src2;   -- Error: src2 ditulis lalu dibaca dalam skrip yang sama.
SELECT * FROM @a;

Solusi 1: Aktifkan mode eksekusi langkah demi langkah

SET odps.sql.step.script.mode=true;
INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0;
@a := SELECT * FROM src2;
SELECT * FROM @a;

Solusi 2: Tulis ulang SQL untuk menggunakan variabel tabel

@a := SELECT * FROM src WHERE key > 0;
INSERT OVERWRITE TABLE src2 SELECT * FROM @a;
SELECT * FROM @a;

Contoh 4: Buat dan hapus tabel temporary

Skrip berikut membuat tabel temporary untuk menyimpan cache hasil antara dari operasi JOIN, membacanya dua kali, lalu menghapusnya.

-- Aktifkan mode eksekusi langkah demi langkah (diperlukan untuk tabel temporary).
SET odps.sql.step.script.mode=true;
DROP TABLE IF EXISTS foo_t1;
CREATE TABLE foo_t1(a BIGINT, b BIGINT);
-- Buat tabel temporary dengan menggunakan JOIN.
CREATE TEMPORARY TABLE t AS
SELECT t1.a AS a, t2.d AS b FROM
  (SELECT 1 a, 2 b) t1
JOIN
  (SELECT 1 c, 10 d) t2
ON t1.a = t2.c;
INSERT INTO foo_t1 SELECT * FROM t UNION ALL SELECT * FROM t;
SELECT * FROM foo_t1;
-- Hapus tabel temporary (harus menjadi pernyataan terakhir dalam skrip).
DROP TABLE t;

Kirimkan skrip

Script mode didukung di MaxCompute Studio, klien MaxCompute (odpscmd), DataWorks, serta SDK Java dan Python.

Klien MaxCompute (odpscmd)

Gunakan odpscmd v0.27 atau yang lebih baru. Setelah Anda menginstal klien MaxCompute, kirimkan skrip menggunakan flag -s:

Buat file skrip, seperti myscript.sql. Kemudian, jalankan perintah berikut dari antarmuka baris perintah Anda untuk menjalankan odpscmd. Untuk informasi lebih lanjut tentang cara menjalankan klien MaxCompute dari baris perintah, lihat Jalankan klien MaxCompute.

..\bin>odpscmd -s myscript.sql
Catatan

Script mode dan variabel tabel tidak didukung di shell interaktif odpscmd. Flag -s adalah opsi baris perintah untuk odpscmd, mirip dengan -f dan -e. Ini bukan perintah di lingkungan interaktif.

DataWorks

Di DataWorks, gunakan node ODPS Script untuk menulis dan menjalankan skrip. Anda kemudian dapat melihat rencana eksekusi dan hasilnya menggunakan URL Logview yang disediakan di output.

Di pojok kiri atas, klik + Create > Create Node. Di bawah kategori MaxCompute, pilih ODPS Script.

Setelah Anda menulis skrip, klik ikon Run pada bilah alat untuk mengeksekusinya. Log output menyediakan URL Logview untuk memeriksa rencana eksekusi dan hasil akhir.

SDK

Anda dapat menjalankan skrip SQL langsung menggunakan SDK Java atau SDK Python. Untuk informasi lebih lanjut, lihat pengenalan SDK Java dan SDK Python.

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.aliyun.odps.Instance;
import com.aliyun.odps.Odps;
import com.aliyun.odps.OdpsException;
import com.aliyun.odps.account.Account;
import com.aliyun.odps.account.AliyunAccount;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.task.SQLTask;
public class SdkTest {
  public static void main(String[] args) throws OdpsException {
    // Pasangan Kunci Akses Alibaba Cloud Anda memberikan akses penuh ke akun Anda dan membawa risiko tinggi.
    // Kami sangat menyarankan agar Anda membuat dan menggunakan Pengguna RAM untuk panggilan API dan operasi harian.
    // Untuk membuat Pengguna RAM, login ke konsol RAM.
    // Contoh ini menunjukkan cara menggunakan Variabel lingkungan untuk menyimpan kredensial Anda.
    // Untuk keamanan, jangan pernah menyematkan Pasangan Kunci Akses Anda secara langsung ke dalam kode.
    Account account = new AliyunAccount(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
    Odps odps = new Odps(account);
    odps.setDefaultProject("your project_name");
    odps.setEndpoint("your end_point");
    String sqlScript = "@a := SELECT * FROM jdbc_test;\n"
                       + "SELECT * FROM @a;";
    // Wajib: Aktifkan script mode.
    Map<String, String> hints = new HashMap<>();
    hints.put("odps.sql.submit.mode", "script");
    Instance instance = SQLTask.run(odps, "your project_name", sqlScript, hints, null);
    instance.waitForSuccess();
    List<Record> recordList = SQLTask.getResult(instance);
    for (Record record : recordList) {
      System.out.println(record.get(0));
      System.out.println(record.get(1));
    }
  }
}
import os
from odps import ODPS
# Pasangan Kunci Akses Alibaba Cloud Anda memberikan akses penuh ke akun Anda dan membawa risiko tinggi.
# Kami sangat menyarankan agar Anda membuat dan menggunakan Pengguna RAM untuk panggilan API dan operasi harian.
# Untuk membuat Pengguna RAM, login ke konsol RAM.
# Contoh ini menunjukkan cara menggunakan Variabel lingkungan untuk menyimpan kredensial Anda.
# Untuk keamanan, jangan pernah menyematkan Pasangan Kunci Akses Anda secara langsung ke dalam kode.
o = ODPS(
    os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"],
    os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"],
    "your project_name",
    "your end_point"
)
sql_script = """
@a := SELECT * FROM jdbc_test;
SELECT * FROM @a;
"""
# Wajib: Aktifkan script mode.
hints = {"odps.sql.submit.mode", "script"}
instance = o.execute_sql(sql_script, hints=hints)
with instance.open_reader() as reader:
    for rec in reader:
        print(rec[0], rec[1])

MaxCompute Studio

Sebelum menjalankan skrip di MaxCompute Studio, lengkapi prasyarat berikut:

  1. Instal IntelliJ IDEA

  2. Tambahkan koneksi proyek

  3. Buat modul MaxCompute Script

Setelah Anda mengompilasi dan menjalankan skrip, MaxCompute Studio menampilkan rencana eksekusi. Meskipun skrip berisi beberapa pernyataan, rencana tersebut dirender sebagai satu DAG.