如何使用 DBIx::Class 进行子选择?

发布于 2024-08-10 22:41:03 字数 318 浏览 2 评论 0 原文

我从 DBIx::Class 开始,我有一个想要在 DBIx::Class 中的子选择,但我很困惑并且无法构建代码。

我的 MySQL 选择是这样的:

Select name from tblCategory where id = (
    Select id from tblCategory where id = (
         Select id from tblRadio where name = "RFM"
    )
);

我读到 DBIx::Class 不支持子选择;是这样吗?如果是这样,遇到这种情况你会怎么做?

I'm starting with DBIx::Class and i have a subselect that wanted to be in DBIx::Class, but i'm getting confused and can't build the code.

My MySQL select is this one:

Select name from tblCategory where id = (
    Select id from tblCategory where id = (
         Select id from tblRadio where name = "RFM"
    )
);

I read that DBIx::Class don't support subselect; is that true? If so, what do you do in situations like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

愛放△進行李 2024-08-17 22:41:04

根据 DBIx::Class: :Manual::Cookbook 有一个新的子查询功能:

my $inside_rs = $schema->resultset('Radio')->search({ name => 'RFM' });

my $rs = $schema->resultset('Category')->search({
    id => { '=' => $inside_rs->get_column('id')->as_query },
});

它被标记为实验性的,所以 YMMV。

但还要注意 SQL::Abstract 其中 DBIx::Class 在构建其查询时使用确实有一个新的使用 -nest 的子查询功能。

According to the DBIx::Class::Manual::Cookbook there is a new Subquery feature:

my $inside_rs = $schema->resultset('Radio')->search({ name => 'RFM' });

my $rs = $schema->resultset('Category')->search({
    id => { '=' => $inside_rs->get_column('id')->as_query },
});

It is marked EXPERIMENTAL so YMMV.

However also note that SQL::Abstract which DBIx::Class uses when building its queries does have a new subquery feature using -nest.

蓝色星空 2024-08-17 22:41:04

难道这不能表示为连接吗?

my $rs = $schema->resultset('Category')->search(
    {   
       'Radio.name' => 'RFM' 
    },
    {   
        'join' => 'Radio'
    }   
);

这假设您在名为“Radio”的类别中具有关系。如果您不这样做,有大量文档可以帮助您设置 关系并了解如何执行加入

至于子查询,最新版本的说明书说它们是 支持,但是实验性

Couldn't this be represented as a join?

my $rs = $schema->resultset('Category')->search(
    {   
       'Radio.name' => 'RFM' 
    },
    {   
        'join' => 'Radio'
    }   
);

This assumes you have a relationship in Category named 'Radio'. If you don't, there's plenty of documentation to help you setup relationships and learn how to perform joins.

As for subqueries, the cookbook for the most recent version says they are supported, but experimental.

殊姿 2024-08-17 22:41:04

那么,当您使用 DBIC 的 search() 方法时,您始终可以提供标量引用来插入文字 SQL。例如:

my $rs = $schema->resultset('Category')->search({ 
              id => \"(Select id from tblRadio where name = 'RFM')" 
});

当我需要比 DBIC 支持的开箱即用的更多表现力时,这就是我过去必须做的事情。但我不知道在这种情况下这是否是“正确”的做法。

Well, you can always supply a scalar reference to insert literal SQL when you're using DBIC's search() method. For example:

my $rs = $schema->resultset('Category')->search({ 
              id => \"(Select id from tblRadio where name = 'RFM')" 
});

That's what I've had to do in the past when I needed more expressiveness than DBIC supported out-of-the-box. I don't know, though, whether that's the "right" thing to do in this case.

路还长,别太狂 2024-08-17 22:41:04

经过与 DBIC 的一番战斗后,我最终获胜:P (是的!)

必须重写一些东西,并且必须忘记子选择并做好关系。

我知道这段代码并不代表最初的问题,但如果我必须再次重写全部内容,我将向您展示我的“项目”的另一部分,其中我又遇到了其他困难。

接下来是我所做的:

DBIx::Class Schema

package DB::Esquema::Passwords;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("Passwords");
__PACKAGE__->add_columns(
  "pswd",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "password",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 20,
  },
  "utilizadorid",
  { data_type => "INT", default_value => undef, is_nullable => 1, size => 11 },
);
__PACKAGE__->set_primary_key("pswd");
__PACKAGE__->belongs_to('utilizadorid' => 'DB::Esquema::Utilizadores');
#belongs_to is not autogenerated, done by hand

与 Utilizadores(用户)有关系

package DB::Esquema::Utilizadores;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("Utilizadores");
__PACKAGE__->add_columns(
  "utilizador",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "nome",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 20,
  },
  "mail",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 30,
  },
);
__PACKAGE__->set_primary_key("utilizador");
__PACKAGE__->has_one('utilizador' => 'DB::Esquema::Passwords', 'utilizadorid');

NEXT(使其工作的脚本)

#!/usr/bin/perl -w

use strict;
use diagnostics; #was important to understand
use lib '/var/www/projectox/lib'; #is where the schema is
use DB::Esquema; #use the Schema

system('clear'); # clear the screen

my $esquema = DB::Esquema->connect("dbi:mysql:dbname=dbswiak","root","");
    $esquema->storage->debug(1);

    #HAD TO USE PREFETCH
    my $resultado = $esquema->resultset('Utilizadores')->search(
    undef,{
         prefetch => { 'utilizador' => 'utilizadorid' }
      }
    )->next();

结果:

    SELECT me.utilizador, me.nome, me.mail, utilizador.pswd, 
utilizador.password, utilizador.utilizadorid, utilizadorid.utilizador, utilizadorid.nome, utilizadorid.mail 
FROM Utilizadores me JOIN Passwords utilizador 
ON utilizador.utilizadorid = me.utilizador 
JOIN Utilizadores utilizadorid ON utilizadorid.utilizador = utilizador.utilizadorid: 

不是我真正想要的,但是最接近的,目标是仅选择我想要的列...也许我会达到该目标

after some fight with DBIC i win in the end :P (YEAH!)

Had to rewrite some stuff, and had to forget the subselects and done the relationships well.

I know that this code don't represent the inicial question, but if i had to rewrite all again, i'm showing you the other part of my "project", where i had again other dificulties.

Next is what i've done:

DBIx::Class Schema

package DB::Esquema::Passwords;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("Passwords");
__PACKAGE__->add_columns(
  "pswd",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "password",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 20,
  },
  "utilizadorid",
  { data_type => "INT", default_value => undef, is_nullable => 1, size => 11 },
);
__PACKAGE__->set_primary_key("pswd");
__PACKAGE__->belongs_to('utilizadorid' => 'DB::Esquema::Utilizadores');
#belongs_to is not autogenerated, done by hand

Has a relationship with Utilizadores (users)

package DB::Esquema::Utilizadores;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("Utilizadores");
__PACKAGE__->add_columns(
  "utilizador",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "nome",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 20,
  },
  "mail",
  {
    data_type => "VARCHAR",
    default_value => undef,
    is_nullable => 1,
    size => 30,
  },
);
__PACKAGE__->set_primary_key("utilizador");
__PACKAGE__->has_one('utilizador' => 'DB::Esquema::Passwords', 'utilizadorid');

NEXT (the script to make it work)

#!/usr/bin/perl -w

use strict;
use diagnostics; #was important to understand
use lib '/var/www/projectox/lib'; #is where the schema is
use DB::Esquema; #use the Schema

system('clear'); # clear the screen

my $esquema = DB::Esquema->connect("dbi:mysql:dbname=dbswiak","root","");
    $esquema->storage->debug(1);

    #HAD TO USE PREFETCH
    my $resultado = $esquema->resultset('Utilizadores')->search(
    undef,{
         prefetch => { 'utilizador' => 'utilizadorid' }
      }
    )->next();

The Result:

    SELECT me.utilizador, me.nome, me.mail, utilizador.pswd, 
utilizador.password, utilizador.utilizadorid, utilizadorid.utilizador, utilizadorid.nome, utilizadorid.mail 
FROM Utilizadores me JOIN Passwords utilizador 
ON utilizador.utilizadorid = me.utilizador 
JOIN Utilizadores utilizadorid ON utilizadorid.utilizador = utilizador.utilizadorid: 

Wasn't what i really wanted, but is the nearest, the goal is to select only the columns i want... maybe i will reach that goal

绝影如岚 2024-08-17 22:41:04

子选择现在是实验性功能,如果您需要能够在编译时允许它们,则非常有用。然而,我发现以下是一个很好的方法:

  1. 大多数子选择可以作为(更快的)联接来完成 - 因此在可能失败的地方使用联接
  2. ,在数据库中创建一个视图并为该视图创建一个架构类。

Subselects are experimental feature now and useful if you need to be able to allow them at compile time. However I find the following to be a good approach:

  1. most subselects can be done as a (faster) join - so use a join where you can
  2. failing that, create a view in the database and a schema class for the view.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文