Redshift:在INSERT上自动截断VARCHAR值还是使用最大长度?

ola*_*lls 8 text amazon-redshift

执行INSERT时,Redshift不允许您插入比表中的目标字段更长/更宽的字符串值.注意:

CREATE TEMPORARY TABLE test (col VARCHAR(5));
-- result: 'Table test created'

INSERT INTO test VALUES('abcdefghijkl');
-- result: '[Amazon](500310) Invalid operation: value too long for type character varying(5);'
Run Code Online (Sandbox Code Playgroud)

解决此问题的一种方法是转换值:

INSERT INTO test VALUES('abcdefghijkl'::VARCHAR(5));
-- result: 'INSERT INTO test successful, 1 row affected'
Run Code Online (Sandbox Code Playgroud)

令人讨厌的部分是,现在我的所有代码都必须在每个INSERT上为每个VARCHAR字段提供这些转换语句,或者应用程序代码必须在尝试构造查询之前截断字符串; 无论哪种方式,这意味着列的宽度规范必须进入应用程序代码,这很烦人.

使用Redshift有没有更好的方法?如果有一些选项可以让服务器截断字符串并执行(并可能引发警告),就像它对MySQL的做法一样.

我能做的一件事就是将这些特定字段声明为非常大的VARCHAR,甚至可能是65535(最大值).

create table analytics.testShort (a varchar(3));
create table analytics.testLong (a varchar(4096));
create table analytics.testSuperLong (a varchar(65535));

insert into analytics.testShort values('abc'); 
insert into analytics.testLong values('abc');
insert into analytics.testSuperLong values('abc');

-- Redshift reports the size for each table is the same, 4 mb
Run Code Online (Sandbox Code Playgroud)

我发现这种方法的一个缺点是,如果在/ join/etc组中使用此列,则会导致性能下降:

https://discourse.looker.com/t/troubleshooting-redshift-performance-extensive-guide/326 (搜索VARCHAR)

我想知道如果你没有伤害,否则如果你打算永远不要在group by,join等中使用这个字段.

在我的场景中需要注意的一些事情:是的,我真的不关心截断时可能丢失的额外字符,不,我没有办法强制执行源文本的长度.我正在从外部来源捕获消息和URL,这些消息和URL通常在字符长度的某个范围内,但有时会有更长的字符.如果它们被截断或不存储,则在我们的应用程序中无关紧要.

Ram*_*asr 12

自动截断字符串以匹配列宽的唯一方法是使用带有选项TRUNCATECOLUMNS的COPY命令

将列中的数据截断为适当的字符数,以使其符合列规范.仅适用于具有VARCHAR或CHAR数据类型的行,以及大小为4 MB或更小的行.

否则,您将需要使用以下两种方法之一来处理字符串的长度:

  1. 显式地将您的值CAST到您想要的VARCHAR:

    INSERT INTO test VALUES(CAST('abcdefghijkl' AS VARCHAR(5)));

  2. 使用LEFT和RIGHT字符串函数截断字符串:

    INSERT INTO test VALUES(LEFT('abcdefghijkl', 5));

注意: CAST应该是您的第一个选项,因为它正确处理多字节字符.LEFT将根据字符数而不是字节截断,如果字符串中有多字节字符,则可能最终超出列的限制.

  • 在转换时+1,它将处理字节.LEFT/RIGHT处理字符,因此如果源字符串是多字节字符串,LEFT/RIGHT可能会返回比预期更长的VARCHAR到字节.IE浏览器.LEFT(foobar,5)可以返回比VARCHAR(5)中存储的字符串更长的字符串. (2认同)