Rails:使用sql查询连接到多个数据库

时间:2017-01-23 03:52:43

标签: ruby-on-rails

我们如何使用单个SQL查询连接两个数据库?我更喜欢在这里使用sql,以提高性能。

  

配置/ database.yml的

SELECT example_dev.*, example_report_dev.*
FROM example_dev.myTable AS firstdb
INNER JOIN example_report_dev.myTable AS seconddb
   ON firstdb.id = seconddb.id

现在在我的一个模型中,我想编写一个查询来从这两个数据库中获取数据

package de.fluxparticle.lab;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableSet;
import javafx.collections.SetChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.Collections;
import java.util.Random;
import java.util.TreeSet;

import static javafx.collections.FXCollections.observableSet;

/**
 * Created by sreinck on 23.01.17.
 */
public class Set2List extends Application {

    private final ObservableSet<Integer> setModel = observableSet(new TreeSet<Integer>());

    @Override
    public void start(Stage primaryStage) throws Exception {
        TableView<Integer> tableView = new TableView<>();
        addColumn(tableView, "Number");

        ObservableList<Integer> list = convertSetToList(setModel);
        tableView.setItems(list);

        Random rnd = new Random();
        scheduleTask(Duration.millis(1000), () -> setModel.add(rnd.nextInt(10)));

        primaryStage.setScene(new Scene(tableView, 800, 600));
        primaryStage.setTitle("Set2List");
        primaryStage.show();
    }

    private static void scheduleTask(Duration interval, Runnable task) {
        Timeline timeline = new Timeline(new KeyFrame(interval, event -> task.run()));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    }

    private static ObservableList<Integer> convertSetToList(ObservableSet<Integer> set) {
        ObservableList<Integer> list = FXCollections.observableArrayList(set);

        set.addListener((SetChangeListener<Integer>) change -> {
            if (change.wasAdded()) {
                Integer added = change.getElementAdded();
                int idx = -Collections.binarySearch(list, added)-1;
                list.add(idx, added);
            } else {
                Integer removed = change.getElementRemoved();
                int idx = Collections.binarySearch(list, removed);
                list.remove(idx);
            }
        });

        return list;
    }

    private static void addColumn(TableView<Integer> tableView, String text) {
        TableColumn<Integer, String> column = new TableColumn<>(text);
        column.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().toString()));
        tableView.getColumns().add(column);
    }

    public static void main(String[] args) {
        launch(args);
    }

}    

谢谢

2 个答案:

答案 0 :(得分:2)

一种方法是使用postgres的dblink

来自文档:

  

dblink执行查询(通常是SELECT,但它可以是任何SQL   在远程数据库中返回行的语句。

首先,您需要在数据库中启用dblink

CREATE EXTENSION dblink;

然后,在您的应用程序中,您可以使用ActiveRecord::Base.connection.execute执行原始查询语句。

我在这里创建了测试设置

  • 数据库db1包含tblfield1的表field2 列。
  • 数据库db2包含tblfield1的表格field2 database.yml列。

两者都有 5行

我的development: adapter: postgresql encoding: unicode database: db1

rails console

来自ActiveRecord::Base.connection.execute(" SELECT * FROM tbl UNION ALL SELECT * FROM dblink('dbname=db2','SELECT * FROM tbl') AS tbl2(field1 varchar, field2 int); ").to_a # [{"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}, {"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}]

'dbname=yourdb port=5432  host=yourhost user=youruser password=yourpwd

这只是一种可行的方法。您可以将dblink连接字符串设置为指向远程服务器(例如:conn1 = { adapter: 'postgresql', encoding: 'utf8', database: 'db1' } conn2 = { adapter: 'postgresql', encoding: 'utf8', database: 'db1' #, more config here - other host, for instance # } arr1 = ActiveRecord::Base.establish_connection(conn1).connection.execute("select * from tbl").to_a # => [{"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}] => [{"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}] arr2 = ActiveRecord::Base.establish_connection(conn2).connection.execute("select * from tbl").to_a # => [{"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}] => [{"field1"=>"one", "field2"=>1}, {"field1"=>"two", "field2"=>2}, {"field1"=>"three", "field2"=>3}, {"field1"=>"four", "field2"=>4}, {"field1"=>"five", "field2"=>5}]

请注意这不是铁路方式。原始查询与模型无关。我建议您仅为特定任务选择此项,例如运行报告。

修改

如果您想为每个数据库创建一个查询,并且不想将其链接到您的模型,则可以使用ActiveRecord::Base.establish_connection,如下所示:

arr1

您将获得两个数据arr2Var workItem=witClient.GetWorkItemAsync(id: [work item id], expand: Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItemExpand.Relations).Result. 数组。

答案 1 :(得分:0)

您可以尝试章鱼宝石:https://github.com/thiagopradi/octopus

  

Octopus是在ActiveRecord中进行数据库分片的更好方法。 Sharding允许同一rails应用程序中的多个数据库。虽然有几个项目实现了Sharding(例如DbCharmer,DataFabric,MultiDb),但每个项目都有其自身的局限性。章鱼项目的主要目标是提供更好的数据库分片方法。