gpt4 book ai didi

sql - 如何使用 `=` 以外的其他运算符创建 DBIx::Class 连接表?

转载 作者:行者123 更新时间:2023-12-02 19:10:18 25 4
gpt4 key购买 nike

摘要

我有一张成对的项目表。我想自连接它,这样我就可以在单个查询中检索该对的两侧。这是有效的 SQL(我认为),SQLite 引擎实际上确实接受它,但我很难让 DBIx::Class 咬紧牙关。

最小示例

package Schema::Half;
use parent 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('half');
__PACKAGE__->add_columns(
whole_id => { data_type => 'INTEGER' },
half_id => { data_type => 'CHAR' },
data => { data_type => 'TEXT' },
);
__PACKAGE__->has_one(dual => 'Schema::Half', {
'foreign.whole_id' => 'self.whole_id',
'foreign.half_id' => 'self.half_id',
# previous line results in a '='
# I'd like a '<>'
});

package Schema;
use parent 'DBIx::Class::Schema';
__PACKAGE__->register_class( 'Half', 'Schema::Half' );

package main;
unlink 'join.db';
my $s = Schema->connect('dbi:SQLite:join.db');
$s->deploy;

my $h = $s->resultset('Half');
$h->populate([
[qw/whole_id half_id data /],
[qw/1 L Bonnie/],
[qw/1 R Clyde /],
[qw/2 L Tom /],
[qw/2 R Jerry /],
[qw/3 L Batman/],
[qw/3 R Robin /],
]);
$h->search({ 'me.whole_id' => 42 }, { join => 'dual' })->first;

最后一行生成以下 SQL:

SELECT me.whole_id, me.half_id, me.data
FROM half me
JOIN half dual ON ( dual.half_id = me.half_id AND dual.whole_id = me.whole_id )
WHERE ( me.whole_id = ? )

我正在尝试使用 DBIx::Class 连接语法来获取 <> dual.half_id之间的运算符和me.half_id ,但到目前为止还没有成功。

我尝试过的事情

文档提示了类似 SQL::Abstract 的语法。

我尝试写has_one关系如下:

__PACKAGE__->has_one(dual => 'Schema::Half', {
'foreign.whole_id' => 'self.whole_id',
'foreign.half_id' => { '<>' => 'self.half_id' },
});

# Invalid rel cond val HASH(0x959cc28)

字符串引用后面的直接 SQL 也无法实现:

__PACKAGE__->has_one(dual => 'Schema::Half', {
'foreign.whole_id' => 'self.whole_id',
'foreign.half_id' => \'<> self.half_id',
});

# Invalid rel cond val SCALAR(0x96c10b8)

解决方法以及为什么它们对我来说不够

我可以使用复杂的 search() 生成正确的 SQL调用,并且没有定义的关系。它非常丑陋,有(太多)硬编码的 SQL。对于遍历关系的每个特定情况,它必须以不可因式分解的方式进行模仿。

我可以通过添加 other_half_id 来解决这个问题列并加入 =关于这一点。这显然是冗余数据。

我什至试图通过专用 View ( CREATE VIEW AS SELECT *, opposite_of(side) AS dual FROM half... )添加冗余来避免所说的冗余,而不是数据库模式,而是代码变得冗余和丑陋,比 search() 更冗余和丑陋。基于的解决方法。最后我没有足够的勇气让它发挥作用。

希望的 SQL

这是我正在寻找的 SQL 类型。请注意,这只是一个示例:我真的希望通过关系来完成它,这样我就可以将其用作 Half除了 search() 之外,还有 ResultSet 访问器的join条款。

sqlite> SELECT * 
FROM half l
JOIN half r ON l.whole_id=r.whole_id AND l.half_id<>r.half_id
WHERE l.half_id='L';
1|L|Bonnie|1|R|Clyde
2|L|Tom|2|R|Jerry
3|L|Batman|3|R|Robin

旁注

我确实也在完全扩展的情况下加入了 self,但我很确定这不是问题。我在这里保持这种方式是为了减少情况,因为它也有助于保持较小的代码大小。

我坚持加入/关系路径而不是复杂的 search()因为我对关联有多种用途,而且我没有找到任何“一刀切”的搜索表达式。

更新较晚

Answering my own question两年后,它曾经是一个缺失的功能,但后来被实现了。

最佳答案

对于那些仍然对此感兴趣的人,它终于在 0.08192 或更早版本中实现了。 (我目前使用的是 0.08192)

一种正确的语法是:

__PACKAGE__->has_one(dual => 'Schema::Half', sub {
my $args = shift;
my ($foreign,$self) = @$args{qw(foreign_alias self_alias)};
return {
"$foreign.whole_id" => { -ident => "$self.whole_id" },
"$foreign.half_id" => { '<>' => { -ident => "$self.half_id" } },
}
});

引文:DBIx::Class Extended Relationships on fREW Schmidt's blog我第一次读到它的地方。

关于sql - 如何使用 `=` 以外的其他运算符创建 DBIx::Class 连接表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/978442/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com