【问题标题】:Can DBIx::Class be used with stored procedures instead of tables?DBIx::Class 可以与存储过程而不是表一起使用吗?
【发布时间】:2015-05-20 21:23:06
【问题描述】:

通过返回结果集而不是表或视图的 mssql 存储过程向我提供了从 db 读取的访问权限。但我希望能够使用 ORM 读取数据。

我尝试使用DBIx::Class::ResultSource::View 执行过程调用(例如EXEC my_stored_proc ?)作为自定义查询,但这不起作用,因为它试图将过程调用转换为选择语句。

有人有其他建议吗?

【问题讨论】:

    标签: perl stored-procedures dbix-class


    【解决方案1】:

    不,没有合理的方法可以在 DBIx::Class 的上下文中执行存储过程。

    据我所知,最接近解决方法的是“使用 ORM”来获取数据库句柄,这是弱汤:

       my @results = $schema->storage->dbh_do(sub{
             my ($storage, $dbh, @args) = @_;
             my $sth = $dbh->prepare('call storedProcNameFooBar()');
             my @data;
             $sth->execute();
             while( my $row = $sth->fetchrow_hashref){
                 push @data, $row;
             }
             return @data;
        },());
    

    [ 详情见 http://metacpan.org/pod/DBIx::Class::Storage::DBI#dbh_do]

    ...因为你的麻烦没有得到 ORM 的任何好处。

    【讨论】:

    • DBIx::Class::Manual::Cookbook docs 部分“使用数据库函数或存储过程”,尽管@stevenl 指出它对 MS SQL Server 没有帮助,因为它显然无法通过SELECT 语句。
    • 也不是 Mysql,我猜也不是 Oracle。我想知道 DBIx:Class 手册作者是否只是在编造。
    • 确实 - 预期的行为是什么? DBIC 如何知道将存储过程或函数返回的数据与哪个 ResultSet 相关联?我认为作者的意思是 SQL 函数中的“函数”,例如“长度”。这并不能解释“存储过程”是如何添加的。
    【解决方案2】:

    你可以使用 register_source

     package My::Schema::User;
    
      use base qw/DBIx::Class/;
    
      # ->load_components, ->table, ->add_columns, etc.
    
      # Make a new ResultSource based on the User class
      my $source = __PACKAGE__->result_source_instance();
      my $new_source = $source->new( $source );
      $new_source->source_name( 'UserFriendsComplex' );
    
      # Hand in your query as a scalar reference
      # It will be added as a sub-select after FROM,
      # so pay attention to the surrounding brackets!
      $new_source->name( \<<SQL );
      ( SELECT u.* FROM user u 
      INNER JOIN user_friends f ON u.id = f.user_id 
      WHERE f.friend_user_id = ?
      UNION 
      SELECT u.* FROM user u 
      INNER JOIN user_friends f ON u.id = f.friend_user_id 
      WHERE f.user_id = ? )
      SQL 
    
      # Finally, register your new ResultSource with your Schema
      My::Schema->register_source( 'UserFriendsComplex' => $new_source );
    

    要使用参数调用,请执行以下操作

    my $friends = [ $schema->resultset( 'UserFriendsComplex' )->search( {
    +}, 
        {
          bind  => [ 12345, 12345 ]
        }
      ) ];
    

    【讨论】:

    • 这个解决方案看起来与我使用 ResultSource::View 所做的非常相似。这种方法的问题在于它将我的 sproc 调用添加为子选择的部分。生成的查询将如下所示:SELECT me.x FROM (EXEC my_stored_proc ?) me 这会导致语法错误并且无法准备语句。我猜这个问题不会是 mssql 特有的,因为我没有看到其他平台也有兼容的语法。
    • 这不能回答问题。这里没有存储过程。
    猜你喜欢
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    相关资源
    最近更新 更多