当我在视图的 WHERE 条件中包含一列时,它与值不匹配。相反,当我在 where 条件下使用 TRIM(column) 时,它工作正常。数据不包含任何尾随空格,因为它是我创建的计算字段。该视图正在从其他视图获取数据。 以下是在您这边重现问题的步骤。
我创建了一个测试。
create table test(id int);
insert into test values(1),(2),(3),(4),(2),(3);
我在它上面创建了一个视图来忽略 id 4。
create or replace view test_view as select * from test where id <> 4;
我使用另一个视图在此视图上创建了一个计算字段。
create view test_view_1 as
Select case id
when 1 then 'Aman'::text
when 2 then 'Boy'::character varying
else 'Active'
end as status from test_view;
现在让我们看看数据。
select * from test_view_1
输出: 状态(列名称)
Aman
Boy
Active
Boy
Active
当我使用 where 条件时,它没有给我任何输出。
select * from test_view_1 where status = 'Aman';
无输出
当我在状态上使用 TRIM 时,它会给出输出。
select * from test_view_1 where TRIM(status) = 'Aman';
输出: 状态 (列名称)
Aman
我很失落。我希望这个问题的逐步描述能够帮助您更好地理解并帮助我。由于一些限制,我需要使用多个视图的视图。我希望我能在这方面找到一些帮助。
注意:当我使用 Redshift 中默认的 COLLATE SENSITIVE 时,这不是问题。当我使用 COLLATE INSENSITIVE 处理数据库时出现了这个问题。
有趣的案例。 我相信您已经发现了新的排序不敏感功能(至少因为它作为数据库功能应用)的 Redshift 错误。 您应该将此提交给 AWS。
这里发生的事情是,整理不敏感正在与块元数据比较交叉。 您会看到 Redshift 将 WHERE 子句值与块元数据值进行比较,以查看需要读入哪些块。只有当 WHERE 子句中引用的列未被函数操作时,才会发生这种情况。 如果未读入某个块,则该块的任何结果都会显示在结果中。 我无法证明这一点,但它符合我进行的实验 - 见下文。 Redshift 正在获取所有 SQL,包括视图定义,并通过查询编译器运行它。 它寻找从 WHERE 子句“安全”向后工作的方法,以查明它是否可以将 WHERE 子句应用于表的块元数据。 由于您的 CASE 语句很简单,因此可以这样:“Aman”仅在 id 为 1 时才会出现,因此请检查元数据中的值是否为 1。当启用校对敏感时,这一切都可以正常工作。
当整理对数据库不敏感时,Redshift 会以某种方式混淆应用此推断的元数据检查。 我能够重现您的示例 - 见下文。
您的 TRIM() 案例有效,因为将函数应用于 WHERE 子句中的列会破坏 Redshift 进行元数据比较的能力。 我将此函数更改为 NVL(),查询再次有效。 这是这个娱乐活动:
-- create database foo COLLATE CASE_INSENSITIVE;
-- switch to this new DB
drop table if exists test cascade;
create table test(id int);
insert into test values(1),(2),(3),(4),(2),(3);
create or replace view test_view as select * from test where id <> 4;
create view test_view_1 as
Select case id
when 1 then 'Aman'::text
when 2 then 'Boy'::character varying
else 'Active'
end as status from test_view;
select * from test_view_1;
select * from test_view_1 where nvl(status,'') = 'Aman';
使查询工作的其他函数示例:
select * from test_view_1 where status||'' = 'Aman';
select * from test_view_1 where translate(status,'x','y') = 'Aman';
毫不奇怪,这个函数没有使查询工作,因为更改字符串大小写对于这个数据库来说是无操作的:
select * from test_view_1 where lower(status) = 'Aman';
除了提交错误报告之外,您还可以像使用 TRIM() 或 WHERE 子句中应用的几乎任何其他函数一样解决此问题。 这意味着如果不进行调整,所有查询都可能遇到此危险,并且可能会导致持续出现问题,直到错误得到修复。 可能还有其他解决方法,但了解真正的原因会让您对任何解决方法充满信心。
现在这只是关于此问题背后机制的理论,但您一定要联系 AWS 支持。