全部產品
Search
文件中心

MaxCompute:CSV/TSV外部表格

更新時間:Sep 12, 2025

本文介紹CSV、TSV格式的OSS外部表格的建立、讀取及寫入方法。

前提條件

  • 已具備訪問OSS的許可權。阿里雲帳號(主帳號)、RAM使用者或RAMRole身份可以訪問OSS外部表格,授權資訊請參見OSS的STS模式授權

  • (可選)已準備好OSS儲存空間(Bucket)、OSS目錄及OSS資料檔案。具體操作請參見建立儲存空間管理目錄簡單上傳

    MaxCompute已支援在OSS側自動建立目錄,對於攜帶外部表格及UDF的SQL語句,您可以通過一條SQL語句執行讀寫外部表格及UDF的操作。原手動建立目錄方式仍然支援。
  • 已建立MaxCompute專案。具體操作請參見建立MaxCompute專案

    由於MaxCompute只在部分地區部署,跨地區的資料連通性可能存在問題,因此建議Bucket與MaxCompute專案所在地區保持一致。
  • 已具備在MaxCompute專案中建立表(CreateTable)的許可權。表操作的許可權資訊請參見MaxCompute許可權

使用限制

  • OSS外部表格不支援cluster屬性。

  • 單個檔案大小不能超過3 GB,如果檔案過大,建議拆分。

注意事項

若CSV/TSV檔案中的列數與外表DDL中的列數量的不一致,讀取CSV/TSV資料時會報錯“列數不匹配”,例如FAILED: ODPS-0123131:User defined function exception - Traceback:java.lang.RuntimeException: SCHEMA MISMATCH:xxx

您可通過在Session層級設定odps.sql.text.schema.mismatch.mode參數,以控制輸出結果:

  • SET odps.sql.text.schema.mismatch.mode=error:表示列數不一致時,系統直接報錯。

  • SET odps.sql.text.schema.mismatch.mode=truncate:表示列數不一致時,超過外表DDL中的列數部分將被丟棄;少於外表DDL中的列數部分,列值將被補充為NULL。

資料類型支援

資料類型

com.aliyun.odps.CsvStorageHandler/

TsvStorageHandler

(內建文本資料解析器)

org.apache.hadoop.hive.serde2.OpenCSVSerde

(內建開來源資料解析器)

TINYINT

已開通

已開通

SMALLINT

已開通

已開通

INT

已開通

已開通

BIGINT

已開通

已開通

BINARY

未開通

未開通

FLOAT

已開通

已開通

DOUBLE

已開通

已開通

DECIMAL(precision,scale)

已開通

已開通

VARCHAR(n)

已開通

已開通

CHAR(n)

已開通

已開通

STRING

已開通

已開通

DATE

已開通

已開通

DATETIME

已開通

已開通

TIMESTAMP

已開通

已開通

TIMESTAMP_NTZ

已開通

未開通

BOOLEAN

已開通

已開通

ARRAY

未開通

未開通

MAP

未開通

未開通

STRUCT

未開通

未開通

JSON

未開通

未開通

壓縮格式支援

當您需要讀寫壓縮屬性的OSS檔案時,需要在建表語句中添加with serdeproperties屬性配置,詳情請參見with serdeproperties屬性參數

壓縮格式

com.aliyun.odps.CsvStorageHandler/

TsvStorageHandler

(內建文本資料解析器)

org.apache.hadoop.hive.serde2.OpenCSVSerde

(內建開來源資料解析器)

GZIP

已開通

已開通

SNAPPY

未開通

已開通

LZO

未開通

已開通

建立外部表格

文法結構

各格式的外部表格文法結構詳情,請參見OSS外部表格

  • 內建文本資料解析器

    CSV格式

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name> 
    (
      <col_name> <data_type>,
      ...
    )
    [COMMENT <table_comment>]
    [PARTITIONED BY (<col_name> <data_type>, ...)] 
    STORED BY 'com.aliyun.odps.CsvStorageHandler'  
    [WITH serdeproperties (
      ['<property_name>'='<property_value>',...]
    )] 
    LOCATION '<oss_location>'
    [tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];

    TSV格式

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name> 
    (
      <col_name> <data_type>,
      ...
    )
    [COMMENT <table_comment>]
    [PARTITIONED BY (<col_name> <data_type>, ...)] 
    STORED BY 'com.aliyun.odps.TsvStorageHandler'  
    [WITH serdeproperties (
      ['<property_name>'='<property_value>',...]
    )] 
    LOCATION '<oss_location>'
    [tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];
  • 內建開來源資料解析器

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
    (
      <col_name> <data_type>,
      ...
    )
    [COMMENT <table_comment>]
    [PARTITIONED BY (<col_name> <data_type>, ...)]
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
    [WITH serdeproperties (
      ['<property_name>'='<property_value>',...]
    )]
    STORED AS TEXTFILE 
    LOCATION '<oss_location>' 
    [tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];

公用參數

公用參數說明請參見基礎文法參數說明

專屬參數

with serdeproperties屬性參數

適用解析器

property_name

使用情境

說明

property_value

預設值

內建文本資料解析器(CsvStorageHandler/TsvStorageHandler)

odps.text.option.gzip.input.enabled

當需要讀取以GZIP方式壓縮的CSV或TSV檔案資料時,請添加該屬性。

CSV、TSV壓縮屬性。配置該參數值為True時,MaxCompute才可以正常讀取壓縮檔,否則會讀取失敗。

  • True

  • False

False

odps.text.option.gzip.output.enabled

當需要將資料以GZIP壓縮方式寫入OSS時,請添加該屬性。

CSV、TSV壓縮屬性。配置該參數值為True時,MaxCompute才能將資料以GZIP壓縮方式寫入OSS,否則不壓縮。

  • True

  • False

False

odps.text.option.header.lines.count

當OSS資料檔案為CSV或TSV,且需要忽略OSS資料檔案中的前N行時,請添加該屬性。

MaxCompute讀取OSS資料檔案時,會忽略指定的行數。

非負整數

0

odps.text.option.null.indicator

當OSS資料檔案為CSV或TSV,且需要定義OSS資料檔案中NULL的解析規則時,請添加該屬性。

通過該參數配置的字串會被解析為SQL中的NULL。例如\N指代NULL,則a,\N,b會解析為a, NULL, b

字串

Null 字元串

odps.text.option.ignore.empty.lines

當OSS資料檔案為CSV或TSV,且需要定義OSS資料檔案中空行的處理規則時,請添加該屬性。

配置該參數值為True時,MaxCompute會忽略資料檔案中的空行,否則會讀取空行。

  • True

  • False

True

odps.text.option.encoding

當OSS資料檔案為CSV或TSV,且OSS資料檔案編碼規則非預設編碼規則時,請添加該屬性。

確保此處配置的編碼規則與OSS資料檔案編碼規則保持一致,否則MaxCompute無法成功讀取資料。

  • UTF-8

  • UTF-16

  • US-ASCII

  • GBK

UTF-8

odps.text.option.delimiter

當需要明確CSV或TSV資料檔案的資料行分隔符號時,請添加該屬性。

確保此處配置的資料行分隔符號可以正確讀取OSS資料檔案的每一列,否則MaxCompute讀取的資料會出現錯位問題。

單個字元

半形逗號(,)

odps.text.option.use.quote

當CSV或TSV資料檔案中的欄位包含換行(CRLF)、雙引號或英文逗號時,請添加該屬性。

當CSV某個欄位中包含換行、雙引號(需要在"前再加"轉義)或英文逗號時,整個欄位必須用雙引號("")括起來作為資料行分隔符號。該參數指定是否識別CSV的資料行分隔符號"

  • True

  • False

False

odps.sql.text.option.flush.header

在往OSS寫資料的時候,檔案塊的第一行為表頭。

只有針對CSV檔案格式生效。

  • True

  • False

False

odps.sql.text.schema.mismatch.mode

當讀取的OSS檔案的資料列數和外部表格的Schema列數不一致時。

指定對於列數不一致行的處理方式。

說明:odps.text.option.use.quote參數值為True時,該功能不生效。

  • error:報錯。

  • truncate:超過外部表格列數部分資料被丟棄;少於外部表格列數部分資料則補null

  • ignore:丟棄不一致的行。

error

內建開來源資料解析器(OpenCSVSerde)

separatorChar

當需要明確以TEXTFILE格式儲存的CSV資料的資料行分隔符號時,請添加該屬性。

指定CSV資料資料行分隔符號。

單個字串

半形逗號(,)

quoteChar

當以TEXTFILE格式儲存的CSV資料中的欄位包含換行、雙引號或英文逗號時,請添加該屬性。

指定CSV資料的引用符。

單個字串

escapeChar

當需要明確以TEXTFILE格式儲存的CSV資料的轉義規則時,請添加該屬性。

指定CSV資料的轉義符。

單個字串

tblproperties屬性參數

適用解析器

property_name

使用情境

說明

property_value

預設值

內建開來源資料解析器(OpenCSVSerde)

skip.header.line.count

當需要忽略以TEXTFILE格式儲存的CSV檔案中的前N行資料時,請添加該屬性。

MaxCompute讀取OSS資料時,會忽略從首行開始指定行數的資料。

非負整數

skip.footer.line.count

當需要忽略以TEXTFILE格式儲存的CSV檔案中的後N行資料時,請添加該屬性。

MaxCompute讀取OSS資料時,會忽略從尾行開始指定行數的資料。

非負整數

mcfed.mapreduce.output.fileoutputformat.compress

當需要將TEXTFILE資料檔案以壓縮方式寫入OSS時,請添加該屬性。

TEXTFILE壓縮屬性。配置該參數值為True時,MaxCompute才可以將TEXTFILE資料檔案以壓縮方式寫入OSS,否則不壓縮。

  • True

  • False

False

mcfed.mapreduce.output.fileoutputformat.compress.codec

當需要將TEXTFILE資料檔案以壓縮方式寫入OSS時,請添加該屬性。

TEXTFILE壓縮屬性。設定TEXTFILE資料檔案的壓縮方式。

說明:只支援property_value中的四種壓縮方式。

  • com.hadoop.compression.lzo.LzoCodec

  • com.hadoop.compression.lzo.LzopCodec

  • org.apache.hadoop.io.compress.SnappyCodec

  • com.aliyun.odps.io.compress.SnappyRawCodec

io.compression.codecs

當OSS資料檔案為Raw-Snappy格式時,請添加該屬性。

配置該參數值為True時,MaxCompute才可以正常讀取壓縮資料,否則MaxCompute無法成功讀取資料。

com.aliyun.odps.io.compress.SnappyRawCodec

寫入資料

MaxCompute寫入文法詳情,請參見寫入文法說明

查詢分析

Smart Parse更靈活的類型能力

針對CSV格式的OSS外部表格,MaxCompute SQL採用2.0資料類型進行讀寫,之前僅支援部分嚴格格式的值,並按照相應的資料類型進行讀寫。現已相容讀取CSV中各種類型的值。具體如下:

Type

Input as String

Output as String

Description

BOOLEAN

  • "true"/"false"

  • "T"/"F"

  • "1"/"0"

  • "Yes"/"No"

  • "Y"/"N"

  • ""(空串讀進表中會被解析為NULL)

說明

解析時會對輸入執行trim()操作。

  • "true"/"false"

  • "true"/"false"

  • "true"/"false"

  • "true"/"false"

  • "true"/"false"

  • ""(NULL被輸出至CSV中為空白串)

不在枚舉值範圍,則解析失敗。

TINYINT

  • "0"

  • "1"

  • "-100"

  • "1,234,567"(千分位標記法,逗號不能作為該數字串的首尾字元)

  • "1_234_567"(Java-style,底線不能作為該數字串的首尾字元)

  • "0.3e2"(科學計數法,其表示的實際數值為整數時可被解析,否則會報錯)

  • "-1e5"(科學計數法)

  • "0xff"(十六進位,大小寫不敏感)

  • "0b1001"(二進位,大小寫不敏感)

  • "4/2"(分數,其表示的實際數值為整數時可被解析,否則會報錯)

  • "1000%"(百分數,其表示的實際數值為整數時可被解析,否則會報錯)

  • "1000‰"(千分數,其表示的實際數值為整數時可被解析,否則會報錯)

  • "1,000 $"(帶貨幣符號)

  • "$ 1,000"(帶貨幣符號)

  • "3M"(K8s-style, 1000進位單位)

  • "2Gi"(K8s-style, 1024進位單位)

  • ""(空串讀進表中會被解析為NULL)

說明
  • 解析時會對輸入執行trim()操作。

  • 如果使用千分位標記法,例如"1,234,567" ,則需要手動設定CSV分隔字元為非英文逗號的其他符號。具體請參見with serdeproperties屬性參數odps.text.option.delimiter的用法。

  • K8s-style支援的1000進位單位包括 K/M/G/P/T,1024進位單位包括 Ki/Mi/Gi/Pi/Ti,詳情請參見resource-management

  • 貨幣符號包括$/¥/€/£/₩/USD/CNY/EUR/GBP/JPY/KRW/IDR/RP

  • "0""1""-100"""在naive模式下也可以被正確解析。

  • "0"

  • "1"

  • "-100"

  • "1234567"

  • "1234567"

  • "30"

  • "-100000"

  • "255"

  • "9"

  • "2"

  • "10"

  • "1"

  • "1000"

  • "1000"

  • "3000000"(1M=1000*1000)

  • "2147483648"(1 Gi=1024*1024*1024)

  • ""(NULL被輸出至CSV中為空白串)

8位整型,超出範圍範圍[-128, 127]則報錯。

SMALLINT

16位整型,超出範圍範圍[-32768, 32767]則報錯。

INT

32位整型,超出範圍範圍[-2147483648, 2147483647]則報錯。

BIGINT

64位整型,超出範圍範圍[-9223372036854775807, 9223372036854775807]則報錯。

說明

-263(即-9223372036854775808)不在範圍範圍內,為SQL引擎的限制。

FLOAT

  • "3.14"

  • "0.314e1"(科學計數法)

  • "2/5"(分數)

  • "123.45%"(百分數)

  • "123.45‰"(千分數)

  • "1,234,567.89"(千分位表示)

  • "1,234.56 $"(帶貨幣符號)

  • "$ 1,234.56"(帶貨幣符號)

  • "1.2M"(K8s-style,1000進位單位)

  • "2Gi"(K8s-style,1024進位單位)

  • "NaN"(大小寫不敏感)

  • "Inf"(大小寫不敏感)

  • "-Inf"(大小寫不敏感)

  • "Infinity"(大小寫不敏感)

  • "-Infinity"(大小寫不敏感)

  • ""(空串讀進表中會被解析為NULL)

說明
  • 解析時會對輸入執行trim()操作。

  • "3.14""0.314e1""NaN""Infinity""-Infinity"""在naive模式下也可以被正確解析。

  • "3.14"

  • "3.14"

  • "0.4"

  • "1.2345"

  • "0.12345"

  • "1234567.89"

  • "1234.56"

  • "1234.56"

  • "1200000"

  • "2147483648"

  • "NaN"

  • "Infinity"

  • "-Infinity"

  • "Infinity"

  • "-Infinity"

  • ""(null被輸出至csv中為空白串)

特殊值(大小寫不敏感)包括:NaN、Inf、-Inf、Intifniy和-Intifniy。在超出範圍範圍時,將報錯;若精度超出,則進行四捨五入截斷。

DOUBLE

  • "3.1415926"

  • "0.314e1"(科學計數法)

  • "2/5"(分數)

  • "123.45%"(百分數)

  • "123.45‰"(千分數)

  • "1,234,567.89"(千分位表示)

  • "1,234.56 $"(帶貨幣符號)

  • "$ 1,234.56"(帶貨幣符號)

  • "1.2M"(K8s-style,1000進位單位)

  • "2Gi"(K8s-style,1024進位單位)

  • "NaN"(大小寫不敏感)

  • "Inf"(大小寫不敏感)

  • "-Inf"(大小寫不敏感)

  • "Infinity"(大小寫不敏感)

  • "-Infinity"(大小寫不敏感)

  • ""(空串讀進表中會被解析為NULL)

說明
  • 解析時會對輸入執行trim()操作。

  • "3.1415926""0.314e1""NaN""Infinity""-Infinity"""在naive模式下也可以被正確解析。

  • "3.1415926"

  • "3.14"

  • "0.4"

  • "1.2345"

  • "0.12345"

  • "1234567.89"

  • "1234.56"

  • "1234.56"

  • "1200000"

  • "2147483648"

  • "NaN"

  • "Infinity"

  • "-Infinity"

  • "Infinity"

  • "-Infinity"

  • ""(NULL被輸出至CSV中為空白串)

特殊值(大小寫不敏感)包括:NaN、Inf、-Inf、Intifniy和-Intifniy。在超出範圍範圍時,將報錯;若精度超出,則進行四捨五入截斷。

DECIMAL

(precision, scale)

以DECIMAL(15,2)為例

  • "3.358"

  • "2/5"(分數)

  • "123.45%"(百分數)

  • "123.45‰"(千分數)

  • "1,234,567.89"(千分位表示)

  • "1,234.56 $"(帶貨幣符號)

  • "$ 1,234.56"(帶貨幣符號)

  • "1.2M"(K8s-style, 1000進位單位)

  • "2Gi"(K8s-style, 1024進位單位)

  • ""(空串讀進表中會被解析為NULL)

說明
  • 解析時會對輸入執行trim()操作。

  • "3.358"""在naive模式下也可以被正確解析。

  • "3.36"(四捨五入)

  • "0.4"

  • "1.23"(四捨五入)

  • "0.12"(四捨五入)

  • "1234567.89"

  • "1234.56"

  • "1234.56"

  • "1200000"

  • "2147483648"

  • ""(NULL被輸出至CSV中為空白串)

整數部分值超出precision-scale

則會報錯;小數部分超出scale,則會進行四捨五入截斷。

CHAR(n)

以CHAR(7)為例

  • "abcdefg"

  • "abcdefghijklmn"

  • "abc"

  • ""(空串讀進表中會被解析為NULL)

  • "abcdefg"

  • "abcdefg"(後續部分被截斷)

  • "abc____"(_表示空格,擴充了4個Null 字元)

  • ""(NULL被輸出至CSV中為空白串)

最大長度為255。長度不足則會填充空格,但空格不參與比較。長度超出n會截斷。

VARCHAR(n)

以VARCHAR(7)為例

  • "abcdefg"

  • "abcdefghijklmn"

  • "abc"

  • ""(空串讀進表中會被解析為NULL)

  • "abcdefg"

  • "abcdefg"(後續部分被截斷)

  • "abc"

  • ""(NULL被輸出至CSV中為空白串)

最大長度為65535。長度超出n會截斷。

STRING

  • "abcdefg"

  • "abc"

  • ""(空串讀進表中會被解析為NULL)

  • "abcdefg"

  • "abc"

  • ""(NULL被輸出至CSV中為空白串)

長度限制為8 MB。

DATE

  • "yyyy-MM-dd"(例如"2025-02-21")

  • "yyyyMMdd"(例如"20250221")

  • "MMM d,yyyy"(例如"October 1,2025")

  • "MMMM d,yyyy"(例如"Oct 1,2025")

  • "yyyy年M月d日"(例如"2025年10月1日")

  • ""(空串讀進表中會被解析為NULL)

說明

您也可以通過自訂odps.text.option.date.io.format控制讀入時的解析方式。例如使用者定義format為 'dd/MM/yyyy#yyyy--MM--dd',則可以解析'21/02/2025''2025--02--21'

  • "2000-01-01"

  • "2000-01-01"

  • ""(NULL被輸出至CSV中為空白串)

  • 無時分秒資訊,改變時區不影響輸出結果。預設輸出格式為"yyyy-MM-dd"

  • 您也可以通過自訂odps.text.option.date.io.format 來控制解析與輸出格式。輸出格式將採用自訂的首個pattern。格式可參考DateTimeFormatter

TIMESTAMP_NTZ

說明

OpenCsvSerde不支援此類型,因為該類型與Hive資料格式不相容。

  • 納秒位長度可為0~9,MaxCompute支援的內建解析格式如下:

    • "yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]"(例如"2000-01-01 00:00:00.123")

    • "yyyy-MM-ddTHH:mm:ss[.SSSSSSSSS]"(例如"2000-01-01T00:00:00.123456789")

    • "yyyyMMddHHmmss"(例如"20000101000000")

    • ""(空串讀進表中會被解析為NULL)

  • 您也可通過自訂odps.text.option.timestamp_ntz.io.format來控制讀入時的解析方式。例如使用者定義format為'ddMMyyyy-HHmmss',則可以解析形如'31102024-103055'的字串。

  • "2000-01-01 00:00:00.123000000"

  • "2000-01-01 00:00:00.123456789"

  • "2000-01-01 00:00:00.000000000"

  • ""(NULL被輸出至CSV中為空白串)

  • 本質為納秒粒度的時間戳記,改變時區資訊不影響輸出結果,即預設使用標準UTC時區輸出結果。預設輸出格式為"yyyy-MM-dd HH:mm:ss.SSSSSSSSS"

  • 您也可以通過自訂odps.text.option.timestamp_ntz.io.format控制解析與輸出格式。格式可參考DateTimeFormatter

DATETIME

  • 毫秒位長度可為0~3,x表示時區位移,假設系統時區為Asia/Shanghai,MaxCompute支援的內建解析格式如下:

    • "yyyy-MM-dd HH:mm:ss[.SSS][x]"(例如"2000-01-01 00:00:00.123")

    • "yyyy-MM-ddTHH:mm:ss[.SSS][x]"(例如"2000-01-01T00:00:00.123+0000")

    • "yyyyMMddHHmmss[x]" (例如"20000101000000+0000")

    • ""(空串讀進表中會被解析為NULL)

  • 您也可通過自訂odps.text.option.datetime.io.format來控制讀入時的解析方式。例如使用者定義format為 'yyyyMMdd-HHmmss.SSS',則可以解析形如'20241031-103055.123'的字串。

假設系統時區為Asia/Shanghai:

  • "2000-01-01 00:00:00.123+0800"

  • "2000-01-01 08:00:00.123+0800"

  • "2000-01-01 08:00:00.000+0800"

  • ""(NULL被輸出至CSV中為空白串)

  • 本質為毫秒粒度的時間戳記,改變時區資訊影響輸出結果。預設輸出格式為"yyyy-MM-dd HH:mm:ss.SSSx"

  • 您可通過odps.sql.timezone修改系統時區,從而控制寫出值的時區位移。

  • 您也可通過自訂odps.text.option.datetime.io.format控制解析與輸出格式。格式可參考:DateTimeFormatter

TIMESTAMP

  • 納秒位長度可為0~9,x表示時區位移,假設系統時區為Asia/Shanghai,MaxCompute支援的內建解析格式:

    • "yyyy-MM-dd HH:mm:ss[.SSSSSSSSS][x]"(例如"2000-01-01 00:00:00.123456")

    • "yyyy-MM-ddTHH:mm:ss[.SSSSSSSSS][x]"(例如"2000-01-01T00:00:00.123+0000")

    • "yyyyMMddHHmmss[x]"(例如"20000101000000+0000")

    • ""(空串讀進表中會被解析為NULL)

  • 您也可通過自訂odps.text.option.timestamp.io.format來控制讀入時的解析方式。例如使用者定義format為'yyyyMMdd-HHmmss',則可以解析形如'20240910-103055'的字串。

(假設系統時區為Asia/Shanghai)

  • "2000-01-01 00:00:00.123456000+0800"

  • "2000-01-01 08:00:00.123000000+0800"

  • "2000-01-01 08:00:00.000000000+0800"

  • ""(NULL被輸出至CSV中為空白串)

  • 本質為納秒粒度的時間戳記,改變時區資訊影響輸出結果。預設輸出格式為"yyyy-MM-dd HH:mm:ss.SSSSSSSSSx"

  • 您可通過odps.sql.timezone修改系統時區,從而控制寫出值的時區位移。

  • 您也可通過自訂odps.text.option.timestamp.io.format控制解析與輸出格式。格式可參考DateTimeFormatter

注意事項

  • 對於任意類型,CSV資料檔案中的Null 字元串被讀入表中後,均會被解析為NULL。

  • 不支援STRUCT/ARRAY/MAP等複雜類型,因為這些複雜類型的值很容易和CSV的常見分隔字元(,)發生衝突導致解析失敗。

  • 暫不支援BINARY/INTERVAL類型,如有需求請聯絡MaxCompute支援人員。

  • 對於資料類型INT/SMALLINT/TINYINT/BIGINT/FLOAT/DOUBLE/DECIMAL,預設的解析能力(DEFAULT)比較豐富。

    如果您只想對基礎的數字串進行解析,可以在tblproperties中將odps.text.option.smart.parse.level參數設定為naive,使解析器僅支援解析普通數字串,例如“123”、“123.456”,其他形態的字串在解析時會報錯。

  • 對於四種日期或時間相互關聯類型DATA/DATATIME/TIMESTAMP/TIMESTAMP_NTZ,在底層代碼中均使用java.time.format.DateTimeFormatter進行處理。MaxCompute內建了若干的預設解析格式,您也可以通過在tblproperties中設定odps.text.option.<date|datetime|timestamp|timestamp_ntz>.io.format來自訂多種解析格式與一種輸出格式,解析格式之間用#分隔。

    • 自訂格式的優先順序高於MaxCompute的內建解析格式,輸出格式將採用第一個自訂格式。

      例如,若您自訂DATE類型的格式串為pattern1#pattern2#pattern3,則可以解析符合pattern1pattern2pattern3的字串,但輸出至檔案時會採用pattern1格式來輸出。詳情請參見DateTimeFormatter

    • 不建議使用 'z' (time-zone name) 作為自訂的時區格式(尤其對於中國區使用者),因為 'z' 在某些上下文中可能存在歧義。

      例如:'CST' 在中國語境下通常表示中國標準時間(UTC+8),然而當 'CST' 被java.time.format.DateTimeFormatter解析時,會被識別為美國中部標準時間(UTC-6),這可能導致非預期的輸入或輸出結果。建議您改用 'x' (zone-offset) 或 'VV' (time-zone ID) 作為時區模式。

使用樣本

說明
  • 執行下述範例程式碼時,請將代碼中的<uid>替換為您的阿里雲帳號ID。

  • 下述樣本中使用的角色為aliyunodpsdefaultrole,如果您想使用其他角色,需要將aliyunodpsdefaultrole替換為目標角色名稱,並為目標角色授予訪問OSS的許可權。

通過內建文本資料解析器建立OSS外部表格

樣本一:非分區表

  1. 樣本資料中的Demo1/目錄建立映射關係。建立OSS外部表格的命令樣本如下。

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external1
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongtitue DOUBLE,
      recordTime STRING,
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler' 
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo1/';
    
    -- 您可以執行desc extended mc_oss_csv_external1;命令查看建立好的OSS外部表格結構資訊。
  2. 查詢非分區外表。

    SELECT * FROM mc_oss_csv_external1;

    返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | 1          | 1          | 51         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | S          |
    | 1          | 2          | 13         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         |
    | 1          | 3          | 48         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         |
    | 1          | 4          | 30         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | W          |
    | 1          | 5          | 47         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | S          |
    | 1          | 6          | 9          | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | S          |
    | 1          | 7          | 53         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | N          |
    | 1          | 8          | 63         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | SW         |
    | 1          | 9          | 4          | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | NE         |
    | 1          | 10         | 31         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | N          |
    +------------+------------+------------+------------+------------------+-------------------+------------+----------------+
  3. 寫入資料至非分區外表,並查看資料是否已成功寫入。

    INSERT INTO mc_oss_csv_external1 VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10','SW');
    SELECT * FROM mc_oss_csv_external1 WHERE recordId=12;

    返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | 1          | 12         | 76         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:10 | SW         |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+

    查看OSS路徑Demo1/下已產生新檔案。image

樣本二:分區表

  1. 樣本資料中的Demo2/目錄建立映射關係。建立OSS外部表格並引入分區資料的命令樣本如下。

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external2
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongtitue DOUBLE,
      recordTime STRING
    )
    PARTITIONED BY (
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler' 
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo2/';
    
    -- 您可以執行DESC EXTENDED mc_oss_csv_external2;命令查看建立好的外部表格結構資訊。
  2. 引入分區資料。當建立的OSS外部表格為分區表時,需要額外執行引入分區資料的操作,更多操作請參見補全OSS外部表格分區資料文法

    MSCK REPAIR TABLE mc_oss_csv_external2 ADD PARTITIONS;
    
    --等效於如下語句。
    ALTER TABLE mc_oss_csv_external2 ADD PARTITION (direction = 'N') 
      PARTITION (direction = 'NE') PARTITION (direction = 'S') 
      PARTITION (direction = 'SW') PARTITION (direction = 'W');
  3. 查詢分區外表。

    SELECT * FROM mc_oss_csv_external2 WHERE direction='NE';

    返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | 1          | 2          | 13         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         |
    | 1          | 3          | 48         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         |
    | 1          | 9          | 4          | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | NE         |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
  4. 寫入資料至分區外表,並查看是否已成功寫入。

    INSERT INTO mc_oss_csv_external2 PARTITION(direction='NE') VALUES(1,12,76,1,46.81006,-92.08174,'9/14/2014 0:10');
    SELECT * FROM mc_oss_csv_external2 WHERE direction='NE' AND recordId=12;

    返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+
    | 1          | 12         | 76         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:10 | NE         |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+

    查看OSS路徑Demo2/direction=NE下已產生新檔案。image

樣本三:壓縮資料

本樣本建立以GZIP壓縮的CSV格式外表,進行資料讀取和寫入操作。

  1. 建立內部表並寫入測試資料,用來進行後續的寫入測試。

    CREATE TABLE vehicle_test(
      vehicleid INT, 
      recordid INT, 
      patientid INT, 
      calls INT, 
      locationlatitute DOUBLE, 
      locationlongtitue DOUBLE, 
      recordtime STRING, 
      direction STRING
    );
    
    INSERT INTO vehicle_test VALUES (1,1,51,1,46.81006,-92.08174,'9/14/2014 0:00','S');
  2. 建立以GZIP壓縮的CSV格式外表,與樣本資料中的Demo3/(壓縮資料)目錄建立映射關係。建立OSS外部表格命令樣本如下。

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external3
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongtitue DOUBLE,
      recordTime STRING,
      direction STRING
    )
    PARTITIONED BY (dt STRING)
    STORED BY 'com.aliyun.odps.CsvStorageHandler' 
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
      'odps.text.option.gzip.input.enabled'='true',
      'odps.text.option.gzip.output.enabled'='true' 
    ) 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo3/';
    
    -- 引入分區資料
    MSCK REPAIR TABLE mc_oss_csv_external3 ADD PARTITIONS;
    
    -- 您可以執行DESC EXTENDED mc_oss_csv_external3;命令查看建立好的外部表格結構資訊。
  3. 使用MaxCompute用戶端,從OSS中讀取資料。命令樣本如下:

    說明

    如果OSS壓縮資料為開來源資料格式,需要在SQL語句前添加set odps.sql.hive.compatible=true;命令,與SQL語句一起提交執行。

    --開啟全表掃描,僅此Session有效。
    SET odps.sql.allow.fullscan=true;
    SELECT recordId, patientId, direction FROM mc_oss_csv_external3 WHERE patientId > 25;

    返回結果如下:

    +------------+------------+------------+
    | recordid   | patientid  | direction  |
    +------------+------------+------------+
    | 1          | 51         | S          |
    | 3          | 48         | NE         |
    | 4          | 30         | W          |
    | 5          | 47         | S          |
    | 7          | 53         | N          |
    | 8          | 63         | SW         |
    | 10         | 31         | N          |
    +------------+------------+------------+
  4. 讀取內部表的資料寫入至OSS外表。

    通過MaxCompute用戶端對外部表格執行INSERT OVERWRITEINSERT INTO命令,將資料寫入OSS。

    INSERT INTO TABLE mc_oss_csv_external3 PARTITION (dt='20250418') SELECT * FROM vehicle_test;

    執行成功後,您可在OSS目錄下查看匯出的檔案。

建立OSS外部表格並指定對應OSS檔案的第一行為表頭

樣本資料oss-mc-testBucket下建立Demo11目錄,並執行如下語句:

--建立外部表格
CREATE EXTERNAL TABLE mf_oss_wtt
(
  id BIGINT,
  name STRING,
  tran_amt DOUBLE
)
STORED BY 'com.aliyun.odps.CsvStorageHandler'
WITH serdeproperties (
  'odps.text.option.header.lines.count' = '1',
  'odps.sql.text.option.flush.header' = 'true'
)
LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/Demo11/';

--插入資料
INSERT OVERWRITE TABLE mf_oss_wtt VALUES (1, 'val1', 1.1),(2, 'value2', 1.3);

--查詢資料
--在建表的時候可以把所有欄位建成string,否則表頭讀取時會報錯。
--或者在建表的時候需要加跳過表頭的參數:'odps.text.option.header.lines.count' = '1'
SELECT * FROM mf_oss_wtt;

返回結果如下:

+----------+--------+------------+
| id       | name   | tran_amt   |
+----------+--------+------------+
| 1        | val1   | 1.1        |
| 2        | value2 | 1.3        |
+----------+--------+------------+

建立OSS外部表格且外部表格列數與OSS資料列數不一致

  1. 樣本資料oss-mc-testBucket下建立demo目錄,並上傳test.csv檔案。test.csv檔案內容如下。

    1,kyle1,this is desc1
    2,kyle2,this is desc2,this is two
    3,kyle3,this is desc3,this is three, I have 4 columns
  2. 建立外部表格。

    1. 指定對於列數不一致的行的處理方式為TRUNCATE

      --刪除表
      DROP TABLE test_mismatch;
      --建立外部表格
      CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch
      (
        id string,
        name string,
        dect string,
        col4 string
      )
      STORED BY 'com.aliyun.odps.CsvStorageHandler'
      WITH serdeproperties ('odps.sql.text.schema.mismatch.mode' = 'truncate')
      LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/';
    2. 指定對於列數不一致的行的處理方式為IGNORE

      --刪除表
      DROP TABLE test_mismatch01;
      --建立外部表格
      CREATE EXTERNAL TABLE IF NOT EXISTS test_mismatch01
      (
        id STRING,
        name STRING,
        dect STRING,
        col4 STRING
      )
      STORED BY 'com.aliyun.odps.CsvStorageHandler'
      WITH serdeproperties ('odps.sql.text.schema.mismatch.mode' = 'ignore')
      LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/';
    3. 查詢表資料。

      • 查詢test_mismatch表。

        SELECT * FROM test_mismatch;
        
        --返回結果
        +----+-------+---------------+---------------+
        | id | name  | dect          | col4          |
        +----+-------+---------------+---------------+
        | 1  | kyle1 | this is desc1 | NULL          |
        | 2  | kyle2 | this is desc2 | this is two   |
        | 3  | kyle3 | this is desc3 | this is three |
        +----+-------+---------------+---------------+
      • 查詢test_mismatch01表。

        SELECT * FROM test_mismatch01;
        
        --返回結果
        +----+-------+----------------+-------------+
        | id | name  | dect           | col4        |
        +----+-------+----------------+-------------+
        | 2  | kyle2 | this is desc2  | this is two  
        +----+-------+----------------+-------------+

通過內建開源解析器建立OSS外部表格

通過內建開源解析器建立OSS外部表格讀取以逗號為分隔字元的檔案,並忽略首行和尾行的資料。

  1. 樣本資料oss-mc-testBucket下建立demo-test目錄,並上傳測試檔案test.csv

    測試檔案包含的資料資訊如下。

    1,1,51,1,46.81006,-92.08174,9/14/2014 0:00,S
    1,2,13,1,46.81006,-92.08174,9/14/2014 0:00,NE
    1,3,48,1,46.81006,-92.08174,9/14/2014 0:00,NE
    1,4,30,1,46.81006,-92.08174,9/14/2014 0:00,W
    1,5,47,1,46.81006,-92.08174,9/14/2014 0:00,S
    1,6,9,1,46.81006,-92.08174,9/15/2014 0:00,S
    1,7,53,1,46.81006,-92.08174,9/15/2014 0:00,N
    1,8,63,1,46.81006,-92.08174,9/15/2014 0:00,SW
    1,9,4,1,46.81006,-92.08174,9/15/2014 0:00,NE
    1,10,31,1,46.81006,-92.08174,9/15/2014 0:00,N
  2. 建立外部表格,並指定分隔字元為逗號,設定忽略首行和尾行參數。

    CREATE EXTERNAL TABLE ext_csv_test08
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongtitue DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
    WITH serdeproperties (
    "separatorChar" = ","
    )
    stored AS textfile
    location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/***/'
    -- 設定忽略首行和尾行參數。
    TBLPROPERTIES (
    "skip.header.line.COUNT"="1",
    "skip.footer.line.COUNT"="1"
    )
    ;
  3. 讀取外部表格。

    SELECT * FROM ext_csv_test08;
    
    -- 返回結果,唯讀了8條,忽略了首行和尾行。
    +------------+------------+------------+------------+------------------+-------------------+------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime | direction  | 
    +------------+------------+------------+------------+------------------+-------------------+------------+------------+
    | 1          | 1          | 51         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | S          | 
    | 1          | 2          | 13         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         | 
    | 1          | 3          | 48         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE         | 
    | 1          | 4          | 30         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | W          | 
    | 1          | 5          | 47         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | S          | 
    | 1          | 6          | 9          | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | S          | 
    | 1          | 7          | 53         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | N          | 
    | 1          | 8          | 63         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | SW         | 
    | 1          | 9          | 4          | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | NE         | 
    | 1          | 10         | 31         | 1          | 46.81006         | -92.08174         | 9/15/2014 0:00 | N          | 
    +------------+------------+------------+------------+------------------+-------------------+------------+------------+

建立CSV格式的OSS外部表格-自訂各種時間資料類型

CSV自訂時間類型的解析與輸出格式詳情,請參見Smart Parse更靈活的類型能力

  1. 建立各時間資料類型的CSV外表(datetime/timestamp/timestamp_ntz)。

    CREATE EXTERNAL TABLE test_csv
    (
      col_date DATE,
      col_datetime DATETIME,
      col_timestamp TIMESTAMP,
      col_timestamp_ntz TIMESTAMP_NTZ
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo/'
    TBLPROPERTIES (
      'odps.text.option.date.io.format' = 'MM/dd/yyyy',
      'odps.text.option.datetime.io.format' = 'yyyy-MM-dd-HH-mm-ss x',
      'odps.text.option.timestamp.io.format' = 'yyyy-MM-dd HH-mm-ss VV',
      'odps.text.option.timestamp_ntz.io.format' = 'yyyy-MM-dd HH:mm:ss.SS'
    );
    
    INSERT OVERWRITE test_csv 
      VALUES(DATE'2025-02-21', DATETIME'2025-02-21 08:30:00', TIMESTAMP'2025-02-21 12:30:00', TIMESTAMP_NTZ'2025-02-21 16:30:00.123456789');
  2. 插入資料後,CSV檔案的內容為:

    02/21/2025,2025-02-21-08-30-00 +08,2025-02-21 12-30-00 Asia/Shanghai,2025-02-21 16:30:00.12
  3. 再次讀資料,可以看到結果。

    SELECT * FROM test_csv;

    返回結果如下:

    +------------+---------------------+---------------------+------------------------+
    | col_date   | col_datetime        | col_timestamp       | col_timestamp_ntz      |
    +------------+---------------------+---------------------+------------------------+
    | 2025-02-21 | 2025-02-21 08:30:00 | 2025-02-21 12:30:00 | 2025-02-21 16:30:00.12 |
    +------------+---------------------+---------------------+------------------------+