Saiba como criar, ler e gravar tabelas externas para dados CSV e TSV armazenados no Object Storage Service (OSS).
Observações de uso
Tabelas externas do OSS não suportam a propriedade de cluster.
O tamanho de um único arquivo não pode exceder 2 GB. Divida arquivos maiores que 2 GB.
O MaxCompute e o OSS devem estar na mesma região.
Tipos de dados suportados
Para obter mais informações sobre os tipos de dados do MaxCompute, consulte Versão 1.0 dos tipos de dados e Versão 2.0 dos tipos de dados.
Para mais detalhes sobre o SmartParse, consulte Compatibilidade flexível de tipos do Smart Parse.
Tipo | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (Integrado) | org.apache.hadoop.hive.serde2.OpenCSVSerde (Código aberto) |
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 |
Formatos de compactação suportados
Ao ler ou gravar arquivos compactados no OSS, inclua o atributo with serdeproperties na instrução CREATE TABLE. Para mais informações, consulte Parâmetros do atributo with serdeproperties.
Formato de compactação | com.aliyun.odps.CsvStorageHandler/ TsvStorageHandler (Integrado) | org.apache.hadoop.hive.serde2.OpenCSVSerde (Código aberto) |
GZIP | ||
SNAPPY | ||
LZO | ||
ZSTD |
Evolução de schema suportada
Operação | Suportado | Descrição |
Adicionar coluna |
| |
Remover coluna | Esta operação não é recomendada, pois pode causar incompatibilidade entre o schema e os dados. | |
Alterar ordem das colunas | Evite esta operação, já que ela pode gerar divergências entre o schema e os dados. | |
Alterar tipo de dado da coluna | Para obter uma lista das conversões de tipos de dados suportadas, consulte Alterar tipo de dado da coluna. | |
Renomear coluna | ||
Modificar comentário da coluna | O comentário deve ser uma string válida com comprimento máximo de 1.024 bytes. Caso contrário, ocorrerá um erro. | |
Alterar nulabilidade da coluna | Operação não suportada. As colunas aceitam valores nulos por padrão. |
Configuração de parâmetros
O schema de uma tabela externa CSV ou TSV mapeia as colunas do arquivo por posição. Se o número de colunas em um arquivo do OSS não corresponder ao número de colunas no schema da tabela externa, utilize o parâmetro odps.sql.text.schema.mismatch.mode para definir como lidar com linhas incompatíveis.
-
Quando
odps.sql.text.schema.mismatch.modeestiver definido como truncate, as modificações nas colunas terão os seguintes efeitos:Os dados compatíveis com o novo schema serão lidos conforme o esperado.
-
Os dados existentes que utilizam o schema antigo são lidos com base no novo schema.
Por exemplo, se você adicionar uma coluna a uma tabela, os dados históricos dessa coluna aparecerão como NULL durante a leitura.
-
Se
odps.sql.text.schema.mismatch.modeestiver configurado como ignore, as alterações nas colunas resultarão no seguinte comportamento:A leitura de dados conformes ao novo schema ocorre normalmente.
-
Dados legados com o schema anterior são interpretados segundo o novo schema.
Por exemplo, ao adicionar uma coluna à tabela, linhas inteiras de dados históricos sem essa nova coluna serão descartadas na leitura.
-
Caso
odps.sql.text.schema.mismatch.modetenha o valor error, as mudanças nas colunas provocarão estes efeitos:Dados alinhados ao novo schema são lidos corretamente.
-
A leitura de dados antigos segue o novo schema.
Por exemplo, se uma coluna for adicionada à tabela, ocorrerá um erro ao tentar ler dados históricos que não possuam a nova coluna.
Criar uma tabela externa
Sintaxe
Built-in text parser
CSV format
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 format
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>',...)];
Built-in open-source parser
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>',...)];
Parâmetros comuns
Para obter mais informações sobre parâmetros comuns, consulte Parâmetros básicos de sintaxe.
Parâmetros específicos de formato
WITH SERDEPROPERTIES parameters
Parser aplicável | Parâmetro | Caso de uso | Descrição | Valor | Padrão |
Parser integrado de dados de texto (CsvStorageHandler/TsvStorageHandler) | odps.text.option.gzip.input.enabled | Utilize esta propriedade para ler arquivos CSV ou TSV compactados no formato GZIP. | Propriedade de compactação CSV e TSV. Defina esta propriedade como |
| False |
odps.text.option.gzip.output.enabled | Use esta propriedade para gravar dados no OSS em formato compactado GZIP. | Propriedade de compactação CSV e TSV. Configure como |
| False | |
odps.text.option.header.lines.count | Esta propriedade permite ignorar as primeiras N linhas de um arquivo CSV ou TSV no OSS. | Especifica o número de linhas de cabeçalho a serem ignoradas desde o início do arquivo durante a leitura dos dados. | Inteiro não negativo | 0 | |
odps.text.option.null.indicator | Utilize esta propriedade para definir uma string personalizada que representa um valor NULL nos dados. | O MaxCompute interpreta a string especificada como um valor Por exemplo, para interpretar | string | string vazia | |
odps.text.option.ignore.empty.lines | Use esta propriedade para definir como tratar linhas vazias em um arquivo CSV ou TSV. | Se |
| True | |
odps.text.option.encoding | Aplique esta propriedade quando o arquivo de dados não utilizar a codificação padrão UTF-8. | A codificação especificada aqui deve corresponder à codificação real do arquivo. Uma incompatibilidade causa falhas na leitura. |
| UTF-8 | |
odps.text.option.delimiter | Utilize esta propriedade para especificar o delimitador de colunas em arquivos CSV ou TSV. | Certifique-se de que o delimitador especificado separa corretamente as colunas no seu arquivo de dados para evitar desalinhamento. | Caractere único | Vírgula (,) | |
odps.text.option.use.quote | Use esta propriedade quando um campo em um arquivo CSV ou TSV contiver quebras de linha (CRLF), aspas duplas ou o delimitador de colunas. | Quando um campo em um arquivo CSV contém uma nova linha, aspas duplas (é necessário adicionar outra |
| False | |
odps.sql.text.option.flush.header | Esta propriedade serve para gravar um cabeçalho de tabela como a primeira linha em cada bloco de arquivo no OSS. | Esta propriedade aplica-se apenas a arquivos CSV. |
| False | |
odps.sql.text.schema.mismatch.mode | Utilize esta propriedade quando uma linha no arquivo de dados tiver um número de colunas diferente do schema da tabela externa. | Define como lidar com linhas cuja contagem de colunas não corresponde ao schema da tabela. Nota: Este recurso não funciona se |
| error | |
odps.text.option.zstd.input.enabled | Habilite esta propriedade para ler arquivos CSV ou TSV compactados no formato ZSTD. | Propriedade de compactação CSV e TSV. Defina como True para que o MaxCompute leia arquivos compactados em ZSTD. Caso contrário, a leitura falhará. |
| False | |
odps.text.option.zstd.output.enabled | Utilize esta propriedade para gravar dados no OSS usando compactação ZSTD. | Propriedade de compactação CSV e TSV. Configure como True para compactar dados no formato ZSTD ao gravar no OSS. Senão, os dados serão gravados sem compactação. |
| False | |
Parser de dados integrado de código aberto (OpenCSVSerde) | separatorChar | Use esta propriedade para especificar o delimitador de colunas para dados CSV armazenados como TEXTFILE. | Especifica o delimitador de colunas. | Um único caractere | Vírgula (,) |
quoteChar | Utilize esta propriedade quando campos em dados CSV contiverem caracteres especiais, como o delimitador ou quebras de linha. | Define o caractere usado para colocar campos entre aspas. | Um único caractere | Nenhum | |
escapeChar | Esta propriedade permite especificar o caractere de escape para dados CSV armazenados como TEXTFILE. | Indica o caractere utilizado para escapar caracteres especiais dentro de um campo. | Um único caractere | Nenhum |
tblproperties parameters
Parser aplicável | Parâmetro | Caso de uso | Descrição | Valor | Padrão |
Parser de dados integrado de código aberto (OpenCSVSerde) | skip.header.line.count | Utilize esta propriedade para pular as primeiras N linhas de um arquivo CSV armazenado como TEXTFILE. | Especifica quantas linhas de cabeçalho ignorar no início do arquivo durante a leitura. | Inteiro não negativo | Nenhum |
skip.footer.line.count | Use esta propriedade para ignorar as últimas N linhas de um arquivo CSV armazenado como TEXTFILE. | Define o número de linhas de rodapé a serem puladas no final do arquivo durante a leitura. | Inteiro não negativo | Nenhum | |
mcfed.mapreduce.output.fileoutputformat.compress | Aplique esta propriedade para gravar dados TEXTFILE no OSS com compactação. | Propriedade de compactação TEXTFILE. Se definida como |
| False | |
mcfed.mapreduce.output.fileoutputformat.compress.codec | Utilize esta propriedade para especificar o codec de compactação ao gravar dados TEXTFILE compactados no OSS. | Propriedade de compactação TEXTFILE. Especifica o codec de compactação para saída TEXTFILE. Nota: O MaxCompute suporta apenas os quatro codecs listados na coluna |
| Nenhum | |
io.compression.codecs | Use esta propriedade quando o arquivo de dados no OSS estiver compactado no formato Raw-Snappy. | Permite que o MaxCompute leia dados compactados em Raw-Snappy. Sem essa configuração, a operação de leitura falha. | com.aliyun.odps.io.compress.SnappyRawCodec | Nenhum | |
odps.text.option.bad.row.skipping | Esta propriedade serve para ignorar dados incorretos em arquivos CSV armazenados no OSS. | Controla se o MaxCompute ignora linhas consideradas dados incorretos ou relata um erro. |
| Nenhum |
Gravar dados
Para obter detalhes sobre a sintaxe de gravação no MaxCompute, consulte Sintaxe de gravação.
Consulta e análise
Consulte Sintaxe de consulta para obter detalhes sobre a sintaxe SELECT.
Consulte Otimização de consultas para saber mais sobre a otimização de planos de consulta.
Para mais informações, consulte BadRowSkipping.
BadRowSkipping
O recurso BadRowSkipping permite ignorar linhas inválidas em dados CSV que, de outra forma, causariam falha na consulta. Essa configuração controla o tratamento de erros e não afeta a forma como o formato de dados subjacente é analisado.
Parâmetros
-
Parâmetro no nível da tabela:
odps.text.option.bad.row.skippingrigid: Força o salto de linhas. Esta configuração não pode ser substituída por configurações no nível de sessão ou projeto.flexible: Habilita o salto de linhas. Esta configuração é flexível, permitindo que seja substituída por configurações no nível de sessão ou projeto.
-
Parâmetros no nível de
session/project-
O parâmetro
odps.sql.unstructured.text.bad.row.skippingpode substituir um parâmetro de tabelaflexible, mas não um parâmetrorigid.on: Ativa o recurso. Se o recurso não estiver configurado para a tabela, ele será ativado por padrão.off: Desativa o recurso. Se a tabela estiver configurada como flexible, o recurso será desativado. Caso contrário, a configuração do parâmetro da tabela será usada.<null> or invalid input: A configuração no nível da tabela é utilizada.
-
odps.sql.unstructured.text.bad.row.skipping.debug.num: Especifica o número de resultados de erro a serem impressos no stdout no Logview.O valor máximo é 1000.
Se o valor for <=0, este recurso será desativado.
Se o valor for inválido, este recurso será desativado.
-
-
Interação entre parâmetros no nível de sessão e propriedades da tabela
tbl property
session flag
resultado
rigid
on
On, Forçado on
off
<null>, um valor inválido ou parâmetro não configurado
flexible
on
On
off
Off, Desativado pela sessão
<null>, um valor inválido ou parâmetro não configurado
On
Não configurado
on
On, Ativado pela sessão
off
Off
<null>, um valor inválido ou parâmetro não configurado
-
Prepare os dados
Faça upload do arquivo de dados de teste csv_bad_row_skipping.csv, que contém linhas inválidas, para um diretório no OSS, como
oss-mc-test/badrow/. -
Crie as tabelas externas CSV
Os exemplos a seguir mostram três cenários baseados em diferentes combinações de parâmetros no nível de tabela e de sessão.
Parâmetro da tabela:
odps.text.option.bad.row.skipping = flexible | rigid | <not set>Flag de sessão:
odps.sql.unstructured.text.bad.row.skipping = on | off | <not set>
Parameter not set
-- No table-level parameter is set. Queries will fail on bad rows unless overridden by the session-level flag. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flag ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>';Flexible skipping
-- The table is configured to skip bad rows, but this can be disabled by the session-level flag. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_flexible ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'flexible' -- Enables flexible skipping, which can be disabled at the session level. );Rigid skipping
-- The table is configured to forcibly skip bad rows. This cannot be disabled at the session level. CREATE EXTERNAL TABLE test_csv_bad_data_skipping_rigid ( a INT, b INT ) STORED BY 'com.aliyun.odps.CsvStorageHandler' WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole' ) location '<oss://<your-bucket-name>/<your-file-path>/>' tblproperties ( 'odps.text.option.bad.row.skipping' = 'rigid' -- Forces skipping on. ); -
Verifique os resultados da consulta
Parameter not set
-- The following command enables skipping, but it is immediately overridden by the next command in this example. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command disables skipping and is the active setting for the SELECT query below, causing it to fail. SET odps.sql.unstructured.text.bad.row.skipping=off; -- You can use this command to print details of skipped rows when skipping is enabled. It has no effect here because the query fails. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flag;A consulta falha com o seguinte erro: FAILED: ODPS-0123131:User defined function exception
Flexible skipping
-- The following command enables skipping, but it is immediately overridden by the next command in this example. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command disables skipping, overriding the table's 'flexible' setting. It is the active setting for the SELECT query below, causing it to fail. SET odps.sql.unstructured.text.bad.row.skipping=off; -- Print details of up to 10 bad rows at the session level. The maximum is 1,000. A value of 0 or less disables printing. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_flexible;A consulta falha com o seguinte erro: FAILED: ODPS-0123131:User defined function exception
Rigid skipping
-- This command is redundant because the 'rigid' setting already enforces skipping. SET odps.sql.unstructured.text.bad.row.skipping=on; -- This command attempts to disable skipping, but it is ignored because the 'rigid' table setting cannot be overridden. SET odps.sql.unstructured.text.bad.row.skipping=off; -- This command prints details for up to 10 bad rows that are skipped by the 'rigid' setting. SET odps.sql.unstructured.text.bad.row.skipping.debug.num=10; SELECT * FROM test_csv_bad_data_skipping_rigid;O seguinte resultado é retornado:
+------------+------------+ | a | b | +------------+------------+ | 1 | 26 | | 5 | 37 | +------------+------------+ "true"/"false"
"T"/"F"
"1"/"0"
"Yes"/"No"
"Y"/"N"
"" (Uma string vazia é analisada como NULL.)
"true"/"false"
"true"/"false"
"true"/"false"
"true"/"false"
"true"/"false"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"0"
"1"
"-100"
"1,234,567" (notação com separador de milhar; vírgulas não podem estar no início ou fim da string)
"1_234_567" (estilo Java; underscores não podem estar no início ou fim da string)
"0.3e2" (notação científica; analisado apenas se o valor for um inteiro; caso contrário, ocorre um erro)
"-1e5" (notação científica)
"0xff" (hexadecimal, insensível a maiúsculas/minúsculas)
"0b1001" (binário, insensível a maiúsculas/minúsculas)
"4/2" (fração; analisado apenas se o valor for um inteiro; caso contrário, ocorre um erro)
"1000%" (porcentagem; analisado apenas se o valor for um inteiro; caso contrário, ocorre um erro)
"1000‰" (por mil; analisado apenas se o valor for um inteiro; caso contrário, ocorre um erro)
"1,000 $" (com símbolo monetário)
"$ 1,000" (com símbolo monetário)
"3M" (estilo K8s, unidade base-1000)
"2Gi" (estilo K8s, unidade base-1024)
"" (Uma string vazia é analisada como NULL.)
Durante a análise, a entrada passa por uma operação
trim().Se você usar notação com separador de milhar, como "1,234,567", deverá definir o delimitador CSV como um caractere diferente de vírgula. Para mais informações, consulte o uso de
odps.text.option.delimiterem atributos with serdeproperties.As unidades base-1000 estilo K8s suportadas incluem K, M, G, P e T. As unidades base-1024 incluem Ki, Mi, Gi, Pi e Ti. Para mais informações, consulte resource-management.
Os símbolos monetários suportados incluem
$/¥/€/£/₩/USD/CNY/EUR/GBP/JPY/KRW/IDR/RP.As strings
"0","1","-100"e""também podem ser analisadas corretamente nonaive mode."0"
"1"
"-100"
"1234567"
"1234567"
"30"
"-100000"
"255"
"9"
"2"
"10"
"1"
"1000"
"1000"
"3000000" (1M = 1000*1000)
"2147483648" (1 Gi = 102410241024)
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"3.14"
"0.314e1" (notação científica)
"2/5" (fração)
"123.45%" (porcentagem)
"123.45‰" (por mil)
"1,234,567.89" (notação com separador de milhar)
"1,234.56 $" (com símbolo monetário)
"$ 1,234.56" (com símbolo monetário)
"1.2M" (estilo K8s, unidade base-1000)
"2Gi" (estilo K8s, unidade base-1024)
"NaN" (insensível a maiúsculas/minúsculas)
"Inf" (insensível a maiúsculas/minúsculas)
"-Inf" (insensível a maiúsculas/minúsculas)
"Infinity" (insensível a maiúsculas/minúsculas)
"-Infinity" (insensível a maiúsculas/minúsculas)
"" (Uma string vazia é analisada como NULL.)
A entrada passa por uma operação
trim()durante a análise.As strings
"3.14","0.314e1","NaN","Infinity","-Infinity"e""também podem ser analisadas corretamente nonaive mode."3.14"
"3.14"
"0.4"
"1.2345"
"0.12345"
"1234567.89"
"1234.56"
"1234.56"
"1200000"
"2147483648"
"NaN"
"Infinity"
"-Infinity"
"Infinity"
"-Infinity"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"3.1415926"
"0.314e1" (notação científica)
"2/5" (fração)
"123.45%" (porcentagem)
"123.45‰" (por mil)
"1,234,567.89" (notação com separador de milhar)
"1,234.56 $" (com símbolo monetário)
"$ 1,234.56" (com símbolo monetário)
"1.2M" (estilo K8s, unidade base-1000)
"2Gi" (estilo K8s, unidade base-1024)
"NaN" (insensível a maiúsculas/minúsculas)
"Inf" (insensível a maiúsculas/minúsculas)
"-Inf" (insensível a maiúsculas/minúsculas)
"Infinity" (insensível a maiúsculas/minúsculas)
"-Infinity" (insensível a maiúsculas/minúsculas)
"" (Uma string vazia é analisada como NULL.)
Durante a análise, uma operação
trim()é executada na entrada.As strings
"3.1415926","0.314e1","NaN","Infinity","-Infinity"e""também podem ser analisadas corretamente nonaive mode."3.1415926"
"3.14"
"0.4"
"1.2345"
"0.12345"
"1234567.89"
"1234.56"
"1234.56"
"1200000"
"2147483648"
"NaN"
"Infinity"
"-Infinity"
"Infinity"
"-Infinity"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"3.358"
"2/5" (fração)
"123.45%" (porcentagem)
"123.45‰" (por mil)
"1,234,567.89" (notação com separador de milhar)
"1,234.56 $" (com símbolo monetário)
"$ 1,234.56" (com símbolo monetário)
"1.2M" (estilo K8s, unidade base-1000)
"2Gi" (estilo K8s, unidade base-1024)
"" (Uma string vazia é analisada como NULL.)
Durante a análise, a operação
trim()é executada na entrada.As strings
"3.358"e""também podem ser analisadas corretamente nonaive mode."3.36" (arredondado)
"0.4"
"1.23" (arredondado)
"0.12" (arredondado)
"1234567.89"
"1234.56"
"1234.56"
"1200000"
"2147483648"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"abcdefg"
"abcdefghijklmn"
"abc"
"" (Uma string vazia é analisada como NULL.)
"abcdefg"
"abcdefg" (O restante da string é truncado.)
"abc____" (preenchido com quatro caracteres de espaço, representados por
_)"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"abcdefg"
"abcdefghijklmn"
"abc"
"" (Uma string vazia é analisada como NULL.)
"abcdefg"
"abcdefg" (O restante da string é truncado.)
"abc"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"abcdefg"
"abc"
"" (Uma string vazia é analisada como NULL.)
"abcdefg"
"abc"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
"yyyy-MM-dd" (por exemplo, "2025-02-21")
"yyyyMMdd" (por exemplo, "20250221")
"MMM d,yyyy" (por exemplo, "Oct 1,2025")
"MMMM d,yyyy" (por exemplo, "October 1,2025")
"" (Uma string vazia é analisada como NULL.)
"2000-01-01"
"2000-01-01"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
Este tipo não contém informações de hora, portanto, alterar o fuso horário não afeta a saída. O formato de saída padrão é
"yyyy-MM-dd".Você pode definir a propriedade
odps.text.option.date.io.formatpara definir formatos personalizados de análise e saída. O primeiro padrão definido é usado para saída. Para sintaxe de padrões, consulte DateTimeFormatter.A parte de nanossegundos pode ter de 0 a 9 dígitos. Os formatos integrados suportados pelo MaxCompute são:
"yyyy-MM-dd HH:mm:ss[.SSSSSSSSS]" (por exemplo, "2000-01-01 00:00:00.123")
"yyyy-MM-ddTHH:mm:ss[.SSSSSSSSS]" (por exemplo, "2000-01-01T00:00:00.123456789")
"yyyyMMddHHmmss" (por exemplo, "20000101000000")
"" (Uma string vazia é analisada como NULL.)
Você também pode definir a propriedade
odps.text.option.timestamp_ntz.io.formatpara controlar o formato de análise. Por exemplo, se você definir o formato como'ddMMyyyy-HHmmss', o MaxCompute poderá analisar uma string como'31102024-103055'."2000-01-01 00:00:00.123000000"
"2000-01-01 00:00:00.123456789"
"2000-01-01 00:00:00.000000000"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
Este tipo representa um carimbo de data/hora com precisão de nanossegundos. Ele não é afetado pelo fuso horário da sessão e sua saída tem como padrão o fuso horário UTC. O formato de saída padrão é
"yyyy-MM-dd HH:mm:ss.SSSSSSSSS".Você pode definir a propriedade
odps.text.option.timestamp_ntz.io.formatpara definir formatos personalizados de análise e saída. Para sintaxe de padrões, consulte DateTimeFormatter.A parte de milissegundos pode ter de 0 a 3 dígitos. [x] representa o deslocamento do fuso horário. Supondo que o fuso horário do sistema seja Asia/Shanghai, os formatos integrados suportados pelo MaxCompute são:
"yyyy-MM-dd HH:mm:ss[.SSS][x]" (por exemplo, "2000-01-01 00:00:00.123")
"yyyy-MM-ddTHH:mm:ss[.SSS][x]" (por exemplo, "2000-01-01T00:00:00.123+0000")
"yyyyMMddHHmmss[x]" (por exemplo, "20000101000000+0000")
"" (Uma string vazia é analisada como NULL.)
Você também pode definir a propriedade
odps.text.option.datetime.io.formatpara controlar o formato de análise. Por exemplo, se você definir o formato como'yyyyMMdd-HHmmss.SSS', o MaxCompute poderá analisar uma string como'20241031-103055.123'."2000-01-01 00:00:00.123+0800"
"2000-01-01 08:00:00.123+0800"
"2000-01-01 08:00:00.000+0800"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
Este tipo representa um carimbo de data/hora com precisão de milissegundos. O valor de saída é afetado pelo fuso horário da sessão. O formato de saída padrão é
"yyyy-MM-dd HH:mm:ss.SSSx".Você pode definir a propriedade
odps.sql.timezonepara alterar o fuso horário do sistema, o que controla o deslocamento do fuso horário do valor de saída.Você também pode definir a propriedade
odps.text.option.datetime.io.formatpara definir formatos personalizados de análise e saída. Para sintaxe de padrões, consulte DateTimeFormatter.A parte de nanossegundos pode ter de 0 a 9 dígitos. [x] representa o deslocamento do fuso horário. Supondo que o fuso horário do sistema seja Asia/Shanghai, os formatos integrados suportados pelo MaxCompute são:
"yyyy-MM-dd HH:mm:ss[.SSSSSSSSS][x]" (por exemplo, "2000-01-01 00:00:00.123456")
"yyyy-MM-ddTHH:mm:ss[.SSSSSSSSS][x]" (por exemplo, "2000-01-01T00:00:00.123+0000")
"yyyyMMddHHmmss[x]" (por exemplo, "20000101000000+0000")
"" (Uma string vazia é analisada como NULL.)
Você também pode definir a propriedade
odps.text.option.timestamp.io.formatpara controlar o formato de análise. Por exemplo, se você definir o formato como'yyyyMMdd-HHmmss', o MaxCompute poderá analisar uma string como'20240910-103055'."2000-01-01 00:00:00.123456000+0800"
"2000-01-01 08:00:00.123000000+0800"
"2000-01-01 08:00:00.000000000+0800"
"" (Valores NULL são gravados como uma string vazia no arquivo CSV.)
Este tipo representa um carimbo de data/hora com precisão de nanossegundos. O valor de saída é afetado pelo fuso horário da sessão. O formato de saída padrão é
"yyyy-MM-dd HH:mm:ss.SSSSSSSSSx".Você pode definir a propriedade
odps.sql.timezonepara alterar o fuso horário do sistema, o que controla o deslocamento do fuso horário do valor de saída.Você também pode definir a propriedade
odps.text.option.timestamp.io.formatpara definir formatos personalizados de análise e saída. Para sintaxe de padrões, consulte DateTimeFormatter.-
Regras gerais
Para qualquer tipo de dado, uma string vazia no arquivo de dados CSV é analisada como NULL ao ser lida em uma tabela.
-
Tipos de dados não suportados
Tipos complexos (STRUCT, ARRAY, MAP): Não suportados. Valores desses tipos frequentemente contêm caracteres como a vírgula (
,), que podem entrar em conflito com delimitadores CSV comuns e causar falhas na análise.BINARY e INTERVAL: Atualmente não suportados. Se precisar de suporte para esses tipos, entre em contato com o suporte técnico do MaxCompute.
-
Tipos numéricos (INT, DOUBLE, etc.)
Para tipos de dados numéricos como INT, SMALLINT, TINYINT, BIGINT, FLOAT, DOUBLE e DECIMAL, o MaxCompute oferece amplas capacidades de análise padrão.
Se precisar analisar apenas strings numéricas básicas, defina a propriedade
odps.text.option.smart.parse.levelcomonaiveemtblproperties. No modo naive, o parser suporta apenas formatos simples como "123" e "123.456". Analisar outros formatos de string causa um erro.
-
Tipos de data e hora (DATE, TIMESTAMP, etc.)
A classe
java.time.format.DateTimeFormatterprocessa todos os quatro tipos de data e hora:DATE, DATETIME, TIMESTAMP e TIMESTAMP_NTZ.Formatos padrão: O MaxCompute possui vários formatos de análise integrados.
-
Formatos personalizados:
Defina múltiplos formatos de análise e um formato de saída configurando a propriedade
odps.text.option.<date|datetime|timestamp|timestamp_ntz>.io.formatemtblproperties.Utilize o símbolo de cerquilha (
#) para separar múltiplos padrões de análise.Formatos personalizados têm precedência sobre os formatos integrados. O primeiro padrão personalizado é usado para saída.
Exemplo: Se você definir a string de formato personalizado para o tipo DATE como
pattern1#pattern2#pattern3, o MaxCompute poderá analisar strings que correspondam apattern1,pattern2oupattern3. No entanto, ao gravar dados em um arquivo, a saída sempre usará o formato especificado porpattern1. Para mais informações, consulte DateTimeFormatter.
-
Nota importante sobre o padrão de fuso horário 'z'
Evite usar 'z' (nome do fuso horário) em formatos personalizados, especialmente para usuários na China, pois é ambíguo.
Em vez disso, use 'x' (deslocamento de zona) ou 'VV' (ID do fuso horário) para o padrão de fuso horário.
Exemplo: 'CST' geralmente significa China Standard Time (UTC+8) na China. No entanto, quando
java.time.format.DateTimeFormatteranalisa 'CST', ele interpreta como US Central Standard Time (UTC-6), o que pode causar resultados inesperados de entrada ou saída.
Um projeto MaxCompute. Consulte Criar um projeto MaxCompute.
Um bucket do OSS na mesma região do seu projeto MaxCompute. Consulte Criar um bucket e Gerenciar pastas. O MaxCompute pode criar pastas no OSS automaticamente — não é necessário criá-las antes de executar SQL.
Permissões de acesso ao OSS via conta Alibaba Cloud, usuário Resource Access Management (RAM) ou função RAM. Consulte Autorizar acesso no modo STS para OSS.
A permissão
CreateTableno seu projeto MaxCompute. Consulte Permissões do MaxCompute.-
Mapeie a tabela externa para o diretório
Demo1/dos dados de amostra. Utilize o comando a seguir para criar uma tabela externa 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/'; -- You can run the `desc extended mc_oss_csv_external1;` command to view the schema of the created OSS external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM alvo e conceda a ela as permissões necessárias para acessar o OSS. -
Consulte a tabela externa não particionada.
SELECT * FROM mc_oss_csv_external1;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 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 | +------------+------------+------------+------------+------------------+-------------------+------------+----------------+ -
Grave dados na tabela externa não particionada e verifique se a gravação foi bem-sucedida.
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;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | SW | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+Verifique se um novo arquivo aparece no diretório
Demo1/no OSS.Após a gravação dos dados, visualize o arquivo de resultado gerado
20250606054845430gpwnhakujm16_M1_1_0_0-0_TableSink1-0-.csv(0,046 KB) no caminho correspondente do OSS, juntamente com o arquivo de dados originalvehicle.csv(0,45 KB). -
Mapeie a tabela externa para o diretório
Demo2/dos dados de amostra. O comando de exemplo a seguir cria uma tabela externa OSS particionada.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/'; -- You can run the `DESC EXTENDED mc_oss_csv_external2;` command to view the schema of the created external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM alvo e conceda a ela as permissões necessárias para acessar o OSS. -
Importe os dados da partição. Se você criar uma tabela externa OSS particionada, também deverá importar os dados da partição. Para mais informações, consulte Tabelas externas OSS.
MSCK REPAIR TABLE mc_oss_csv_external2 ADD PARTITIONS; -- This is equivalent to the following statement. ALTER TABLE mc_oss_csv_external2 ADD PARTITION (direction = 'N') PARTITION (direction = 'NE') PARTITION (direction = 'S') PARTITION (direction = 'SW') PARTITION (direction = 'W'); -
Consulte a tabela externa particionada.
SELECT * FROM mc_oss_csv_external2 WHERE direction='NE';O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 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 | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ -
Grave dados na tabela externa particionada e verifique se a gravação foi bem-sucedida.
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;O comando retorna o seguinte resultado:
+------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | vehicleid | recordid | patientid | calls | locationlatitute | locationlongtitue | recordtime | direction | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 1 | 12 | 76 | 1 | 46.81006 | -92.08174 | 9/14/2014 0:10 | NE | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+Verifique se um novo arquivo foi gerado no diretório
Demo2/direction=NEno OSS.O arquivo de dados de partição gerado automaticamente
20250606062610590gocsdsoujm16_M1_1_0_0-0_TableSink1-0-.csvpode ser visto na lista de arquivos do OSS, indicando que os dados foram gravados com sucesso no caminho de partição correspondente no OSS. -
Crie uma tabela interna e insira dados de teste para um teste de gravação subsequente.
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'); -
Crie uma tabela externa CSV compactada em GZIP e mapeie-a para o diretório
Demo3/(que contém dados compactados) dos dados de amostra. O comando de exemplo a seguir cria a tabela externa 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/'; -- Import partition data. MSCK REPAIR TABLE mc_oss_csv_external3 ADD PARTITIONS; -- You can run the `DESC EXTENDED mc_oss_csv_external3;` command to view the schema of the created external table.Este exemplo usa a função RAM
aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substituaaliyunodpsdefaultrolepelo nome da sua função RAM alvo e conceda a ela as permissões necessárias para acessar o OSS. -
Use um cliente MaxCompute para ler dados do OSS:
NotaSe os dados compactados no OSS estiverem em um formato de dados de código aberto, adicione o comando
set odps.sql.hive.compatible=true;antes da instrução SQL e envie-os juntos para execução.--Enable a full table scan for the current session only. SET odps.sql.allow.fullscan=true; SELECT recordId, patientId, direction FROM mc_oss_csv_external3 WHERE patientId > 25;O comando retorna o seguinte resultado:
+------------+------------+------------+ | recordid | patientid | direction | +------------+------------+------------+ | 1 | 51 | S | | 3 | 48 | NE | | 4 | 30 | W | | 5 | 47 | S | | 7 | 53 | N | | 8 | 63 | SW | | 10 | 31 | N | +------------+------------+------------+ -
Leia dados da tabela interna e grave-os na tabela externa OSS.
Execute o comando
INSERT OVERWRITEouINSERT INTOem uma tabela externa a partir do cliente MaxCompute para gravar dados no OSS.INSERT INTO TABLE mc_oss_csv_external3 PARTITION (dt='20250418') SELECT * FROM vehicle_test;Após a execução bem-sucedida do comando, visualize o arquivo exportado no diretório do OSS.
-
Crie um diretório
demono bucketoss-mc-testdos dados de amostra e faça upload do arquivotest.csv. O arquivotest.csvcontém o seguinte conteúdo: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 -
Crie as tabelas externas.
-
Defina o método de tratamento para linhas com contagens de colunas inconsistentes como
TRUNCATE.-- Drop the table. DROP TABLE test_mismatch; -- Create the external table. 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/'; -
Especifique o método de tratamento para linhas com contagens de colunas inconsistentes como
IGNORE.-- Drop the table. DROP TABLE test_mismatch01; -- Create the external table. 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/'; -
Consulte os dados nas tabelas.
-
Consulte a tabela
test_mismatch.SELECT * FROM test_mismatch; --Returned result +----+-------+---------------+---------------+ | 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 | +----+-------+---------------+---------------+ -
Consulte a tabela
test_mismatch01.SELECT * FROM test_mismatch01; --Returned result +----+-------+----------------+-------------+ | id | name | dect | col4 | +----+-------+----------------+-------------+ | 2 | kyle2 | this is desc2 | this is two +----+-------+----------------+-------------+
-
-
-
Crie um diretório
demo-testno bucketoss-mc-testdos dados de amostra e faça upload do arquivo test.csv.O arquivo de teste contém os seguintes dados:
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 -
Crie a tabela externa, especifique a vírgula como separador e defina parâmetros para ignorar as linhas de cabeçalho e rodapé.
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/***/' -- Set parameters to ignore the header and footer rows. TBLPROPERTIES ( "skip.header.line.COUNT"="1", "skip.footer.line.COUNT"="1" ) ; -
Leia dados da tabela externa.
SELECT * FROM ext_csv_test08; -- The result includes 8 rows of data because the header and footer rows are ignored. +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ | 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 | 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 | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+ -
Crie uma tabela externa CSV que usa vários tipos de dados de tempo, como
DATE,DATETIME,TIMESTAMPeTIMESTAMP_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'); -
Após a inserção dos dados, o conteúdo do arquivo CSV é o seguinte:
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 -
Consulte os dados novamente para visualizar o resultado.
SELECT * FROM test_csv;O comando retorna o seguinte resultado:
+------------+---------------------+---------------------+------------------------+ | 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 | +------------+---------------------+---------------------+------------------------+ -
Sintoma
Este erro ocorre quando a contagem de colunas em uma linha de um arquivo CSV ou TSV não corresponde à definida no DDL da tabela externa. O MaxCompute relata um erro semelhante a
FAILED: ODPS-0123131:User defined function exception - Traceback:java.lang.RuntimeException: SCHEMA MISMATCH:xxx. -
Resolução
Controle como o MaxCompute lida com a incompatibilidade definindo o parâmetro
odps.sql.text.schema.mismatch.modeno nível da sessão:SET odps.sql.text.schema.mismatch.mode=error: Falha a consulta quando ocorre uma incompatibilidade de contagem de colunas. Este é o comportamento padrão.SET odps.sql.text.schema.mismatch.mode=truncate: Se uma linha tiver mais colunas do que o definido no DDL da tabela externa, as colunas extras serão descartadas. Se uma linha tiver menos colunas, as colunas ausentes serão preenchidas com NULL.
Exemplos
Compatibilidade flexível de tipos com Smart Parse
Para tabelas externas formatadas em CSV no OSS, o MaxCompute SQL utiliza o tipo de dados 2.0 para operações de leitura e gravação. Anteriormente, apenas valores em formatos estritos eram suportados. Este recurso oferece compatibilidade flexível de tipos para leitura de uma ampla variedade de formatos de valores em arquivos CSV. As regras específicas de análise estão detalhadas abaixo.
Tipo | Entrada como string | Saída como string | Descrição |
BOOLEAN | Nota Uma operação | A análise falha se a string de entrada não for um dos valores suportados. | |
TINYINT | Nota | Inteiro de 8 bits. Ocorre um erro se o valor estiver fora do intervalo | |
SMALLINT | Inteiro de 16 bits. Ocorre um erro se o valor estiver fora do intervalo | ||
INT | Inteiro de 32 bits. Ocorre um erro se o valor estiver fora do intervalo | ||
BIGINT | Inteiro de 64 bits. Ocorre um erro se o valor estiver fora do intervalo Nota O valor | ||
FLOAT | Nota | Valores especiais (insensíveis a maiúsculas/minúsculas) incluem NaN, Inf, -Inf, Infinity e -Infinity. Ocorre um erro se um valor estiver fora do intervalo. Se a precisão exceder o limite, o valor será arredondado. | |
DOUBLE | Nota | Valores especiais (insensíveis a maiúsculas/minúsculas) incluem NaN, Inf, -Inf, Infinity e -Infinity. Ocorre um erro se um valor estiver fora do intervalo. Se a precisão exceder o limite, o valor será arredondado. | |
DECIMAL (precision, scale) Exemplo: DECIMAL(15,2) | Nota | Ocorre um erro se a parte inteira contiver mais de Um erro é relatado. Se a parte fracionária exceder a escala, o valor será arredondado e truncado. | |
CHAR(n) Exemplo: CHAR(7) | O comprimento máximo é 255. Se uma string de entrada for menor que n, ela será preenchida com espaços à direita, mas esses espaços são ignorados nas comparações. Se uma string de entrada for maior que n, ela será truncada. | ||
VARCHAR(n) Exemplo: VARCHAR(7) | O comprimento máximo é 65.535. Se uma string de entrada for maior que n, ela será truncada. | ||
STRING | O comprimento máximo é 8 MB. | ||
DATE | Nota Você também pode definir a propriedade | ||
TIMESTAMP_NTZ Nota O OpenCsvSerde não suporta este tipo porque é incompatível com o formato de dados Hive. | |||
DATETIME | Supondo que o fuso horário do sistema seja Asia/Shanghai: | ||
TIMESTAMP | (Supondo que o fuso horário do sistema seja Asia/Shanghai) |
Exemplos
Pré-requisitos
Criar uma tabela externa OSS com o parser de texto integrado
Exemplo 1: Tabela não particionada
Exemplo 2: Tabela particionada
Exemplo 3: Dados compactados
Este exemplo mostra como criar uma tabela externa CSV compactada em GZIP e realizar operações de leitura e gravação.
Criar uma tabela externa com linha de cabeçalho
Crie um diretório Demo11 no bucket oss-mc-test dos dados de amostra e execute as seguintes instruções:
--Create the external table.
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 data.
INSERT OVERWRITE TABLE mf_oss_wtt VALUES (1, 'val1', 1.1),(2, 'value2', 1.3);
--Query data.
--When you create the table, you can define all columns as STRING. Otherwise, an error occurs when the header is read.
--Alternatively, add the 'odps.text.option.header.lines.count' = '1' parameter to the table definition to skip the header.
SELECT * FROM mf_oss_wtt;
Este exemplo usa a função RAM aliyunodpsdefaultrole. Se você usar uma função RAM diferente, substitua aliyunodpsdefaultrole pelo nome da sua função RAM alvo e conceda a ela as permissões necessárias para acessar o OSS.
O comando retorna o seguinte resultado:
+----------+--------+------------+
| id | name | tran_amt |
+----------+--------+------------+
| 1 | val1 | 1.1 |
| 2 | value2 | 1.3 |
+----------+--------+------------+
Criar uma tabela externa com colunas incompatíveis
Criar uma tabela externa com o parser de código aberto
Este exemplo mostra como usar o parser integrado de código aberto para criar uma tabela externa OSS que lê um arquivo separado por vírgulas, ignorando as linhas de cabeçalho e rodapé.
Criar uma tabela externa CSV com tipos de tempo personalizados
Para obter detalhes sobre formatos de análise e saída para tipos de tempo personalizados em CSV, consulte Compatibilidade flexível de tipos com Smart Parse.