在Amazon Redshift中,我有一个表格,我需要从多个CSV文件加载数据:
create table my_table (
id integer,
name varchar(50) NULL
email varchar(50) NULL,
processed_file varchar(256) NULL
);
前三列是指文件中的数据。最后一列processed_filed
表示导入记录的文件。
我有Amazon S3中的文件,我不想使用COPY
命令导入它们。类似的东西:
COPY {table_name} FROM 's3://file-key'
WITH CREDENTIALS 'aws_access_key_id=xxxx;aws_secret_access_key=xxxxx'
DATEFORMAT 'auto' TIMEFORMAT 'auto' MAXERROR 0 ACCEPTINVCHARS '*' DELIMITER '\t' GZIP;
是否可以使用COPY命令自动填充第四个processed_file
列,以插入文件名。
我可以在COPY之后做一个UPDATE语句,但我正在处理大量数据,所以理想情况下我想尽可能避免这种情况。
答案 0 :(得分:4)
这是不可能的。
您需要预先处理文件(包括名称列)或在加载后更新数据(但是那时很难同时从多个文件进行批量加载,这是最有效的方法将数据加载到Redshift中。)
答案 1 :(得分:1)
实际上这是可能的。我在没有额外processed_file_name
列的情况下创建和加载数据,然后添加具有默认值的列。这是完整的过程
create table my_table (
id integer,
name varchar(50) NULL
email varchar(50) NULL,
);
COPY {table_name} FROM 's3://file-key'
WITH CREDENTIALS 'aws_access_key_id=xxxx;aws_secret_access_key=xxxxx'
DATEFORMAT 'auto' TIMEFORMAT 'auto' MAXERROR 0 ACCEPTINVCHARS '*' DELIMITER '\t' GZIP;
ALTER TABLE my_table ADD COLUMN processed_file_name varchar(256) NOT NULL DEFAULT '{file-name}';
答案 2 :(得分:1)
在这里您可以尝试使用此自定义逻辑添加新列,在此示例中将文件名添加为 redshift COPY 中的新列
import boto3
import re
s3 = boto3.client('s3')
sql = "DROPSQL , CREATE SQL , COPY SQL" ## here need to pass your actual sqls
def Filter(datalist,keyword):
# Search data based on regular expression in the list
return [val for val in datalist
if re.search(keyword, val)]
def add_new_col(table_name):
drop_sql = ''.join(Filter(sql.split(';'),keyword=table_name+' '))
create_sql = ''.join(Filter(sql.split(';'),keyword=table_name+'\('))
copy_sql = ''.join(Filter(sql.split(';'),keyword=table_name.upper()+'/'))
BUCKET = copy_sql.split(' ')[3].split('/')[2]
folder = '/'.join(copy_sql.split(' ')[3].split('/')[3:-1])+'/'
maintable = copy_sql.split(' ')[1]
print ("BUCKET {}, key_folder {}, maintable {}".format(BUCKET,folder,maintable))
temp_table_drop_sql = drop_sql.replace(table_name,'temp_table')
temp_table_create_sql = create_sql.replace(table_name,'temp_table')
temp_table_copy_sql = copy_sql.replace(table_name.upper(),'temp_table')
temp_table_name_withSchema = temp_table_copy_sql.split(' ')[1]
print ("temp_table_name_withSchema {}".format(temp_table_name_withSchema))
## replace with query execute logic
print(temp_table_drop_sql)
print(temp_table_create_sql)
#####
response = s3.list_objects_v2(
Bucket=BUCKET,
Prefix =folder)
new_column_name = 'filename'
for i in response["Contents"]:
## replace with query execute logic
temp_sql = copy_sql.replace(folder,i["Key"])
temp_sql = temp_sql.replace(table_name.upper(),'temp_table')
print(temp_sql)
## i["Key"] is filename
print("alter table {} ADD COLUMN {} varchar(256) NOT NULL DEFAULT '{}';".format(temp_table_name_withSchema, new_column_name , i["Key"].split('/')[-1]))
print("insert into {} (select * from {})".format(maintable, temp_table_name_withSchema))
print("truncate {}".format(temp_table_name_withSchema))
#####
## replace with query execute logic
print(drop_sql)
########
add_new_col(table_name)