2015-10-14 11 views
6

Quando si esegue INSERT, Redshift non consente di inserire un valore di stringa più lungo/più largo del campo obiettivo nella tabella. Osservare:Redshift: Tronca automaticamente il valore VARCHAR su INSERT o forse usa la lunghezza massima?

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

Una soluzione per questo è di cast del valore:

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

La parte fastidiosa di questo è che ora tutto il mio codice dovrà avere queste dichiarazioni del cast su ogni INSERT per ogni Campo VARCHAR come questo, o il codice dell'applicazione dovrà troncare la stringa prima di provare a costruire la query; in entrambi i casi, significa che la specifica della larghezza della colonna deve entrare nel codice dell'applicazione, che è fastidioso.

C'è un modo migliore per farlo con Redshift? Sarebbe bello se ci fosse qualche possibilità di avere il server solo per troncare la stringa ed eseguire (e magari sollevare un avviso) come fa con MySQL.

Una cosa che potrei fare è dichiarare questi campi particolari come un VARCHAR molto grande, forse anche 65535 (il massimo).

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 

L'unico svantaggio di questo approccio che ho trovato è che causerà brutta prestazione se questa colonna viene utilizzata in un gruppo da/join/etc:

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

Mi chiedo però se non vi è alcun danno se non si pianifica di non utilizzare mai questo campo in gruppo, join e simili.

Alcune cose da notare nel mio scenario: Sì, davvero non mi importa dei caratteri in più che potrebbero essere persi con il troncamento, e no, non ho un modo per far rispettare la lunghezza del testo sorgente. Sto acquisendo messaggi e URL da fonti esterne che generalmente rientrano in un determinato intervallo di lunghezza di caratteri, ma a volte ce ne sono di più lunghi. Non importa nella nostra applicazione se vengono troncati o non in deposito.

risposta

6

L'unico modo per troncare automaticamente le stringhe per abbinare la larghezza della colonna sta utilizzando il comando COPIA con l'opzione TRUNCATECOLUMNS dati

tronca in colonne per il numero appropriato di caratteri in modo che si adatti alla specifica della colonna . Si applica solo alle colonne con un tipo di dati VARCHAR o CHAR e righe di dimensioni pari o inferiori a 4 MB.

In caso contrario, si dovrà prendersi cura della lunghezza delle stringhe utilizzando uno di questi due metodi:

  1. cast esplicito i valori al VARCHAR che si desidera:

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

  2. Utilizzare le funzioni di stringa LEFT and RIGHT per troncare le stringhe:

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

+0

Grazie, sì, questo è quello che abbiamo scelto molto tempo fa. Per inserti di grandi dimensioni, stiamo usando l'opzione troncata per COPY, il che era abbastanza ovvio. Per altre operazioni INSERT e UPDATE fatte altrove, stiamo facendo il CAST usando l'operatore '::'. – olanmills

Problemi correlati