2015-10-14 14 views
6

执行INSERT时,Redshift不允许插入比表中目标字段更长/更宽的字符串值。注意:Redshift:在INSERT上自动截断VARCHAR值或可能使用最大长度?

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

一种解决方法是投值:

INSERT INTO test VALUES('abcdefghijkl'::VARCHAR(5)); 
-- result: 'INSERT INTO test successful, 1 row affected' 

关于这个恼人的是,现在我所有的代码都必须在每一个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 

这种方法,我发现的一个缺点是,它会导致糟糕的表现,如果这列一组使用/加入的/ etc:

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

我想知道,如果没有任何伤害,否则,如果你打算永远不会在群组中使用此字段,加入等。

在我的场景中需要注意的一些事项:是的,我真的不关心可能会因截断而丢失的额外字符,也不会,我没有办法强制源文本的长度。我从外部来源获取消息和URL,这些消息通常落在字符长度的一定范围内,但有时候会有较长的字符。在我们的应用程序中,如果它们被截断或不在存储中并不重要。

回答

6

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

截断数据在列字符的适当数量,以便 它适合列规范。仅适用于具有 VARCHAR或CHAR数据类型以及4 MB或更小行的列。

否则,你将不得不采取使用这两种方法之一的字符串长度的护理:

  1. 显式地转换自己的价值观的VARCHAR你想要的:

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

  2. 使用LEFT and RIGHT字符串函数截断你的字符串:

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

+0

谢谢,是的,这是我们很久以前就已定居的。对于大容量插入,我们使用截断选项来进行COPY,这非常明显。 对于在别处完成的其他INSERT和UPDATE操作,我们使用'::'运算符来执行CAST。 – olanmills