Todos los productos
Search
Centro de documentos

MaxCompute:SQL en modo script

Última actualización: Oct 10, 2026

El modo script compila y envía varias instrucciones SQL como una sola unidad. Genera un único plan de ejecución que se pone en cola una vez y se ejecuta en un solo trabajo. Este enfoque es ideal para canalizaciones de datos ETL, procesamiento por lotes periódico y escenarios de orquestación de consultas que requieren varias instrucciones coordinadas. Admite el modo normal (ejecución atómica, predeterminado) y el modo de ejecución paso a paso (ejecución en serie).

  • El modo script no es compatible con cost estimation. Las tarifas reales dependen de su billing details.

  • Un solo script puede hacer referencia hasta a 10 000 tablas. Cada referencia se cuenta de forma individual, incluidas las referencias repetidas a la misma tabla y las tablas mencionadas en definiciones de vistas.

  • Si la preparación de datos de varios orígenes termina en momentos muy distintos, por ejemplo, uno a la 01:00 y otro a las 07:00, no utilice una variable de tabla para combinarlos en un único trabajo de SQL en modo script.

Casos de uso

  • Reescribir instrucciones complejas: divida las subconsultas profundamente anidadas en una secuencia legible de asignaciones de variables de tabla.

  • Construir canalizaciones de varias instrucciones: combine instrucciones relacionadas lógicamente en un solo trabajo para reducir la sobrecarga de puesta en cola y programación. En el modo normal, todas las instrucciones se ejecutan de forma atómica. En el modo de ejecución paso a paso, las instrucciones se ejecutan en serie, lo cual es ideal para escenarios de lectura posterior a escritura o migraciones desde otras plataformas. Para obtener más información, consulte Execution modes.

Sintaxis

  • Tipos de instrucciones: el modo script admite instrucciones SET, algunas instrucciones DDL e instrucciones DML. No son compatibles las instrucciones que muestran resultados, como DESC y SHOW.

  • Orden de las instrucciones: un script debe seguir el orden fijo SET → DDL → DML. Cada sección puede contener cero o más instrucciones, pero no se pueden intercalar instrucciones de distintas secciones.

-- 1. SET
SET odps.sql.type.system.odps2=true;
[SET odps.stage.reducer.num=xxx;]
[SET odps.sql.step.script.mode=true;] -- Enable step-by-step execution mode
[...]
-- 2. DDL
CREATE TABLE table1 xxx;
[CREATE TEMPORARY TABLE table2 xxx;] -- Create a temporary table
[...]
-- 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;]
[...]

Modos de ejecución

El modo script admite dos modos de ejecución.

Comportamiento

Modo normal (predeterminado)

Modo de ejecución paso a paso

Cómo habilitarlo

Es el comportamiento predeterminado. No se requiere ninguna configuración.

Agregue SET odps.sql.step.script.mode=true; a la sección SET.

Compilación

Todas las instrucciones DML se compilan en un solo plan de ejecución.

Cada instrucción DML se compila en un plan de ejecución independiente. Nota: los scripts muy complejos, como los que tienen miles de líneas o numerosas operaciones, pueden superar los límites de memoria de compilación.

Ejecución

Todas las instrucciones se ejecutan de forma atómica como un solo trabajo, que inicia únicamente cuando todos los datos de entrada están listos. Si alguna instrucción falla, todo el script falla y se revierten todas las operaciones.

Las instrucciones DML se ejecutan en serie. Si una instrucción falla, las instrucciones ejecutadas previamente no se revierten y debe reintentar el script desde el inicio. Se recomienda dividir los scripts grandes en scripts más pequeños.

Lectura posterior a escritura

No es compatible. Se produce un error si escribe y luego lee la misma tabla dentro de un script.

Es compatible, excepto para tablas transaccionales o particionadas.

Tabla temporal

No es compatible.

Es compatible.

Sintaxis DDL

Crear una tabla temporal

Las tablas temporales almacenan en caché los resultados intermedios para reutilizarlos dentro del mismo script. Como dependen de un patrón de lectura posterior a escritura, solo son compatibles con el modo de ejecución paso a paso.

Sintaxis

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

Parámetros

Parámetro

Descripción

table_name

Accesible únicamente dentro del script actual.

LIFECYCLE <days>

Opcional. Número de días que se conserva la tabla antes de que se elimine automáticamente. Valor predeterminado: 1.

AS <select_statement>

Opcional. Llena la tabla con datos de una instrucción SELECT al momento de crearla.

Límites

  • Las tablas temporales requieren el modo de ejecución paso a paso. Agregue SET odps.sql.step.script.mode=true; a la sección SET de su script.

  • Una tabla temporal solo es accesible dentro del script donde se creó.

  • Las tablas temporales no pueden ser tablas particionadas ni tablas transaccionales.

  • Para eliminar explícitamente una tabla temporal, la instrucción DROP TABLE debe ser la última instrucción del script.

  • Evite crear más de 20 tablas temporales en un solo script.

Crear una tabla estándar

El modo script permite crear tablas estándar. Para conocer los detalles de la sintaxis, consulte CREATE TABLE.

Sintaxis DML y DQL

Límites de las instrucciones

  • Instrucciones que muestran resultados: un script solo puede contener una instrucción que genere salida en pantalla, como una instrucción SELECT independiente. Incluir más de una provoca un error. Evite usar este tipo de instrucciones en los scripts.

  • CREATE TABLE AS: esta instrucción se puede usar solo una vez por script y debe ser la última instrucción ejecutable. Se recomienda crear primero la tabla y después insertar los datos.

  • Modos de escritura mixtos: no se pueden usar OVERWRITE e INTO en la misma tabla dentro de un mismo script. Tampoco se pueden mezclar operaciones DML en tablas transaccionales y tablas estándar.

  • Lectura posterior a escritura: en el modo normal, escribir y luego leer una tabla en el mismo script genera un error. Para resolver este problema, utilice una variable de tabla o cambie al modo de ejecución paso a paso. El modo de ejecución paso a paso admite la operación de lectura posterior a escritura, excepto para tablas transaccionales o tablas particionadas. Para ver un ejemplo detallado, consulte Example 3: Read-after-write in normal mode.

Variables

Sintaxis

-- Declare a variable by using @. Supported types include TABLE and any MaxCompute data type.
@var1 <type>
-- Assign a value by using :=
@var1 := <select_statement>

Notas de uso

  • No se puede asignar una variable de tipo tabla a una variable con un tipo de datos específico. Por ejemplo, la siguiente sintaxis no está permitida:

    @a TABLE (name STRING);
    @a := SELECT 'tom';
    @b STRING;
    @b := SELECT * FROM @a;
  • Las variables pueden almacenar valores constantes. Puede convertir el valor de una variable a un valor escalar mediante SELECT * FROM @var. Una constante también se puede almacenar en una tabla de una sola fila, como se muestra en el siguiente ejemplo. Para obtener más información sobre la sintaxis de conversión, consulte subquery.

    @a := SELECT 10;                                         -- Assign the constant 10
    @b := SELECT key, value + (SELECT * FROM @a) FROM t2;   -- Use @a as a scalar
    SELECT * FROM @b;

Instrucciones IF

Utilice las instrucciones IF para controlar el flujo de ejecución según ciertas condiciones.

Sintaxis

-- Single branch
IF (condition) BEGIN
  statements
END
-- Multi-branch
IF (condition) BEGIN
  statements
END ELSE IF (condition2) BEGIN
  statements
END ELSE BEGIN
  statements
END

Notas de uso

  • Si una rama contiene solo una instrucción, las palabras clave BEGIN y END son opcionales, de manera similar a { } en Java.

  • Las instrucciones DDL como CREATE TABLE, ALTER TABLE y TRUNCATE TABLE no son compatibles dentro de una rama IF.

  • La condición admite dos tipos:

    • Expresión booleana: la rama se determina en tiempo de compilación.

    • Subconsulta escalar booleana: la rama se determina en tiempo de ejecución. MaxCompute podría enviar varios trabajos.

Ejemplo 1: en una instrucción IF, la condición es una expresión de tipo BOOLEAN. Este tipo de instrucción IF ELSE puede determinar qué rama ejecutar en tiempo de compilación, como se muestra en el siguiente ejemplo:

@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;

Ejemplo 2: la condición de la instrucción IF es una subconsulta escalar booleana. Para este tipo de instrucción IF ELSE, la rama de ejecución se determina en tiempo de ejecución, lo que obliga a MaxCompute a enviar varios trabajos:

@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;

Ejemplos

Ejemplo 1: ejemplo básico

El siguiente script combina y une datos de tres tablas de origen mediante operaciones JOIN y UNION, y luego inserta los resultados en dos tablas de destino. Todas las instrucciones se compilan en un solo DAG y se ejecutan de forma atómica.

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;

Ejemplo 2: lectura posterior a escritura en modo paso a paso

El siguiente script habilita el modo de ejecución paso a paso para realizar una operación de lectura posterior a escritura dentro del mismo script.

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;

Ejemplo 3: lectura posterior a escritura en modo normal

En el modo normal, escribir y luego leer la misma tabla en un script genera un error. Este ejemplo muestra el error y dos posibles soluciones.

Preparación de datos

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);

Ejemplo de error (lectura posterior a escritura en modo normal)

INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0;
@a := SELECT * FROM src2;   -- Error: src2 is written to and then read from in the same script.
SELECT * FROM @a;

Solución 1: habilitar el modo de ejecución paso a paso

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

Solución 2: reescribir el SQL para usar una variable de tabla

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

Ejemplo 4: crear y eliminar una tabla temporal

El siguiente script crea una tabla temporal para almacenar en caché los resultados intermedios de una operación JOIN, la lee dos veces y luego la elimina.

-- Enable step-by-step execution mode (required for temporary tables).
SET odps.sql.step.script.mode=true;
DROP TABLE IF EXISTS foo_t1;
CREATE TABLE foo_t1(a BIGINT, b BIGINT);
-- Create a temporary table by using a 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;
-- Drop the temporary table (must be the last statement in the script).
DROP TABLE t;

Enviar scripts

El modo script es compatible con MaxCompute Studio, el cliente de MaxCompute (odpscmd), DataWorks y los SDK de Java y Python.

Cliente de MaxCompute (odpscmd)

Utilice odpscmd v0.27 o una versión posterior. Después de instalar el cliente de MaxCompute, envíe un script con la bandera -s:

Cree un archivo de script, por ejemplo, myscript.sql. Luego, ejecute el siguiente comando desde su interfaz de línea de comandos para iniciar odpscmd. Para obtener más información sobre cómo ejecutar el cliente de MaxCompute desde la línea de comandos, consulte Run the MaxCompute client.

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

El modo script y las variables de tabla no son compatibles con el shell interactivo de odpscmd. La bandera -s es una opción de línea de comandos para odpscmd, similar a -f y -e. No es un comando del entorno interactivo.

DataWorks

En DataWorks, utilice un nodo ODPS Script para escribir y ejecutar scripts.

En la esquina superior izquierda, haga clic en + Create > Create Node. En la categoría MaxCompute, seleccione ODPS Script.

Después de escribir el script, haga clic en el icono Run de la barra de herramientas para ejecutarlo. El registro de salida incluye una URL de Logview para consultar el plan de ejecución y los resultados.

SDK

Ejecute scripts SQL directamente con el SDK de Java o el SDK de Python. Para obtener más información, consulte la documentación de Java SDK y Python SDK.

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 {
    // Your Alibaba Cloud AccessKey pair grants full access to your account and carries high risks.
    // We strongly recommend that you create and use a RAM user for API calls and daily operations.
    // To create a RAM user, log on to the RAM console.
    // This example shows how to use environment variables to store your credentials.
    // For security, never hard-code your AccessKey pair into your code.
    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;";
    // Required: Enable 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
# Your Alibaba Cloud AccessKey pair grants full access to your account and carries high risks.
# We strongly recommend that you create and use a RAM user for API calls and daily operations.
# To create a RAM user, log on to the RAM console.
# This example shows how to use environment variables to store your credentials.
# For security, never hard-code your AccessKey pair into your code.
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;
"""
# Required: Enable 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

Antes de ejecutar un script en MaxCompute Studio, complete los siguientes requisitos previos:

  1. Install IntelliJ IDEA

  2. Add a project connection

  3. Create a MaxCompute Script module

Después de ejecutar el script, MaxCompute Studio muestra el plan de ejecución como un solo DAG, incluso cuando el script contiene varias instrucciones.