রেলগুলি কাঁচা এসকিউএল উদাহরণ


239

আমি কীভাবে এই কোডটিকে কাঁচা এসকিউএলে রূপান্তর করতে এবং রেলগুলিতে ব্যবহার করতে পারি? কারণ আমি যখন এই কোডটি হিরকুতে স্থাপন করি তখন একটি অনুরোধের সময়সীমা ত্রুটি হয় I

@payments = PaymentDetail.joins(:project).order('payment_details.created_at desc')
@payment_errors = PaymentError.joins(:project).order('payment_errors.created_at desc')

@all_payments = (@payments + @payment_errors)

3
আপনি কেন কাঁচা এসকিউএল দ্রুত হবে বলে মনে করেন? আপনি কীভাবে এটি একটি এসকিউএল সমস্যা জানেন?
জন নাগলে

ক্যোয়ারী প্ল্যান না দেখে আমি অনুমান করব যে আপনি যে সমস্যাটি করছেন সেটি ক্রিয়েট_এট দ্বারা অর্ডার করা হচ্ছে। আপনি সম্ভবত পুরো টেবিল জুড়ে একটি সিক স্ক্যান করছেন (ওহ এবং প্রকল্পের সারণীটিও আনছেন)। একটি বড় টেবিল এবং আন্ডারপাওয়ার্ড ডিবিতে নিয়ামক পদ্ধতিতে একবারে দু'টি করা (হিরকু ডাটাবেসগুলি সাধারণভাবে টিউন করা হয়, এবং আপনি যে ব্যয় করেন তার জন্য অপেক্ষাকৃত আন্ডার পাওয়ারযুক্ত) আপনার সময়সীমা শেষ হওয়ার সম্ভাবনা রয়েছে। আপনি যদি এই টেবিলগুলিতে প্রচুর সন্নিবেশ না করে থাকেন তবে আপনি বাছাই করা সূচকটি করতে পারেন: devcenter.heroku.com/articles/postgresql-indexes#sorted-indexes
জিম

1
ভাল স্কেল কাটতে সর্বদা দ্রুত হবে (যদি আপনি জানেন যে আপনি কী করছেন)। রেলগুলি কিছু সত্যই বাজে স্কেল করে। এটি ভাল কাজ করে তবে সাধারণ হতে হবে ... সাধারণ হতে হবে। বলেছিল যে জিম সম্ভবত ঠিক আছে .. ইনডেক্সিং তৈরি করা আরও ভাল হবে। আপনার জিজ্ঞাসাটি প্যাগডমিনে চালানোর চেষ্টা করুন (আপনার ডিবি বিপরীতে)
বাশ05

উত্তর:


427

তুমি এটি করতে পারো:

sql = "Select * from ... your sql query here"
records_array = ActiveRecord::Base.connection.execute(sql)

records_array তারপরে এমন কোনও অ্যারেতে আপনার এসকিএল কোয়েরির ফলাফল হতে পারে যার মাধ্যমে আপনি পুনরাবৃত্তি করতে পারেন।


52
পার্শ্ব নোট: records_arrayবিভিন্ন ডাটাবেস অ্যাডাপ্টারগুলির জন্য বিভিন্ন ধরণের হবে। আপনি যদি পিজি ব্যবহার করছেন তবে এটি একটি উদাহরণ হবে PG::Result, না Array
tybro0103

58
এবং তারপরে ফলাফল অ্যারে পেতে আপনাকে valuesএই PG::Resultঅবজেক্টটিতে কল করতে হবে
জবওয়াত ২

3
@ বাশ05 "শ্রেণীর মাধ্যমে এটি অ্যাক্সেস করার পক্ষে" বলতে কী বোঝায়। - এটি কোনও মডেলটিকে আয়নড না করে কীভাবে টেবিলটি অ্যাক্সেস করবেন সে সম্পর্কে আলোচনা করে
Yo Ludke

1
আসলে ওপিতে কোনও মডেল ব্যবহার না করার বিষয়ে উল্লেখ নেই। কীভাবে কাঁচা এসকিএল চালানো যায়। পেমেন্টডেটেল.এক্সেকিউট (স্কয়ার) কাজ করে।
baash05

20
আমি ActiveRecord::Base.connection.exec_queryআরও ভাল পছন্দ করি কারণ এটি এমন কোনও ActiveRecords::Resultবস্তুকে প্রত্যাবর্তন করে যার মতো হ্যাড পদ্ধতি .columnsএবং .rowsশিরোনাম এবং মানগুলি অ্যাক্সেস করতে পারে। হ্যাশগুলির অ্যারেরটি .executeমোকাবেলা করতে ঝামেলা হতে পারে এবং যখন আমি ক্লমের মাধ্যমে একটি স্যাম গ্রুপ নিয়ে দৌড়ে যাই তখন তা আমাকে অপ্রয়োজনীয় ফলাফল দেয়।
ফ্রেঞ্চিও রডরিগস 21

181

আমি জানি এটি পুরানো ... তবে আমার আজ একই সমস্যা ছিল এবং আমি এর সমাধান পেয়েছি:

Model.find_by_sql

আপনি যদি ফলাফলগুলি ইনস্ট্যান্ট করতে চান:

Client.find_by_sql("
  SELECT * FROM clients
  INNER JOIN orders ON clients.id = orders.client_id
  ORDER BY clients.created_at desc
")
# => [<Client id: 1, first_name: "Lucas" >, <Client id: 2, first_name: "Jan">...]

Model.connection.select_all('sql').to_hash

আপনি যদি কেবল মানগুলির একটি হ্যাশ চান:

Client.connection.select_all("SELECT first_name, created_at FROM clients
   WHERE id = '1'").to_hash
# => [
  {"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
  {"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
]

ফলাফল অবজেক্ট:

select_allএকটি resultবস্তু ফেরত দেয় আপনি এটি দিয়ে যাদু জিনিস করতে পারেন।

result = Post.connection.select_all('SELECT id, title, body FROM posts')
# Get the column names of the result:
result.columns
# => ["id", "title", "body"]

# Get the record values of the result:
result.rows
# => [[1, "title_1", "body_1"],
      [2, "title_2", "body_2"],
      ...
     ]

# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
      {"id" => 2, "title" => "title_2", "body" => "body_2"},
      ...
     ]

# ActiveRecord::Result also includes Enumerable.
result.each do |row|
  puts row['title'] + " " + row['body']
end

সূত্র:

  1. অ্যাক্টিভেকর্ড - এসকিউএল দ্বারা ফাইন্ডিনিগ
  2. পাগল নেভিগেশন রুবি - সক্রিয় রেকর্ড ফল

9
#find_by_sqlআমি যা চেয়েছিলাম ঠিক তাই, আপনাকে অনেক ধন্যবাদ।
শেলভাচু 29:25

# খালি_বাই_ এসকিউএল !!
স্টিভেন এল।

28

আপনি কাঁচা কোয়েরি ব্যবহার করে কার্যকর করতে পারেন ActiveRecord। এবং আমি এসকিউএল ব্লকের সাথে যাওয়ার পরামর্শ দেব

query = <<-SQL 
  SELECT * 
  FROM payment_details
  INNER JOIN projects 
          ON projects.id = payment_details.project_id
  ORDER BY payment_details.created_at DESC
SQL

result = ActiveRecord::Base.connection.execute(query)

হাই .. এই কোয়েরিতে প্যারামিটারগুলি পাস করার কোনও উপায় আছে কি?
অক্ষয় গোয়াল

@ অক্ষয়গইল আপনি ব্লকের মধ্যে সাধারণ রুবি স্ট্রিং ইন্টারপোলেশন ব্যবহার করতে পারেন। SELECT * FROM users WHERE users.id = #{ user.id }
নাথান বেক

2
আপনি এটি করতে পারলে এটি আপনাকে এসকিউএল ইঞ্জেকশনের সম্ভাবনা প্রকাশ করতে পারে
দীপক মহাকালে

26

উভয় টেবিলের জন্য একটি একক জিজ্ঞাসা রাখতে আপনি সরাসরি এসকিউএল করতে পারেন। আমি আশা করি যে লোকেরা সরাসরি স্ট্রিংয়ের মধ্যে ভেরিয়েবল স্থাপন করা থেকে বিরত রাখবে (এসকিউএল ইঞ্জেকশন বিপদ), যদিও এই উদাহরণটির প্রয়োজনটি নির্দিষ্ট করে নি:

@results = []
ActiveRecord::Base.connection.select_all(
  ActiveRecord::Base.send(:sanitize_sql_array, 
   ["... your SQL query goes here and ?, ?, ? are replaced...;", a, b, c])
).each do |record|
  # instead of an array of hashes, you could put in a custom object with attributes
  @results << {col_a_name: record["col_a_name"], col_b_name: record["col_b_name"], ...}
end

সম্পাদনা : হুই যেমন বলেছেন, একটি সহজ উপায় ActiveRecord::Base.connection.execute("...")। আরেকটি উপায় ActiveRecord::Base.connection.exec_query('...').rows। এবং আপনি দেশীয় প্রস্তুত বিবৃতি ব্যবহার করতে পারেন, যেমন পোস্টগ্রাগ ব্যবহার করে, কাঁচা_ সংযোগ দিয়ে প্রস্তুত বিবৃতি তৈরি করা যেতে পারে, https://stackoverflow.com/a/13806512/178651 তে বর্ণিত হিসাবে এক্সিকিউটিরিপ্রেড

আপনি অ্যাক্টিভেকর্ড রিলেশনাল কোয়েরিতে কাঁচা এসকিউএল টুকরোও রাখতে পারেন: http://guides.rubyonrails.org/active_record_querying.html এবং সমিতি, স্কোপ ইত্যাদিতে আপনি সম্ভবত একই এসকিউএলটি অ্যাক্টিভেকর্ড রিলেশনাল কোয়েরিতে তৈরি করতে পারেন এবং এর সাথে দুর্দান্ত জিনিসগুলি করতে পারেন আর্নেল হিসাবে আর্নেল http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/ এ উল্লেখ করেছেন । এবং, অবশ্যই অন্যান্য ওআরএম, রত্ন ইত্যাদি রয়েছে

যদি এটি প্রচুর ব্যবহৃত হয় এবং সূচকগুলি যুক্ত করা অন্য কার্যকারিতা / সংস্থান সংক্রান্ত সমস্যার কারণ না করে, পেমেন্ট_ডেটেলস.ক্রিয়েটেড_এটের জন্য এবং পেমেন্ট_অরফারস.ক্রিয়েট_এটের জন্য ডিবিতে একটি সূচক যুক্ত করার বিষয়টি বিবেচনা করুন।

যদি প্রচুর রেকর্ড এবং সমস্ত রেকর্ড একসাথে প্রদর্শিত না হয়, পৃষ্ঠাগুলি ব্যবহার করে বিবেচনা করুন:

যদি আপনাকে প্যাগিনেট লাগানোর দরকার হয় তবে প্রথমে ডিবিতে পেমেন্ট_রেকর্ডস নামে একটি ভিউ তৈরি করা বিবেচনা করুন যা পেমেন্ট_ডেটেলস এবং পেমেন্ট_অর্টিয়ারস টেবিলগুলিকে একত্রিত করে, তারপরে দেখার জন্য একটি মডেল রাখুন (যা কেবলমাত্র পঠনযোগ্য হবে)। কিছু ডিবি উপাদানযুক্ত দৃষ্টিভঙ্গি সমর্থন করে যা পারফরম্যান্সের জন্য ভাল ধারণা হতে পারে।

এছাড়াও রেলস সার্ভার এবং ডিবি সার্ভার, কনফিগারেশন, ডিস্ক স্পেস, নেটওয়ার্কের গতি / বিলম্বিতা / ইত্যাদি pro প্রক্সিমিটি ইত্যাদির উপর হার্ডওয়্যার বা ভিএম স্পেকগুলি বিবেচনা করুন এবং আপনি যদি না করেন তবে রেল অ্যাপ্লিকেশনটির চেয়ে আলাদা সার্ভার / ভিএম-তে ডিবি স্থাপন বিবেচনা করুন etc ।


যেহেতু প্রশ্নকর্তা তারিখ অনুসারে বাছাই করছেন আমি মনে করি পৃষ্ঠাগুলি সাহায্য করবে না? আমি এসকিউএল-তে গভীরতম নই তবে আমার বোধগম্যতা হ'ল মূল পোস্টে ক্যোয়ারীটি সাজানোর জন্য পুরো টেবিলটি আনতে হবে - কেবল তখনই ফলাফল সীমাবদ্ধ হতে পারে। আমি সন্দেহ করি যে ক্যোয়ারী পরিকল্পনার সিংহভাগ অর্ডার ক্লজে রয়েছে।
জিম রুরবেল

@ জিমউরউবেল পৃষ্ঠাগুলি সম্পর্কিত অনুচ্ছেদটি স্পষ্ট করে বলেছেন- শব্দটি কিছুটা বাদ ছিল না।
গ্যারি এস ওয়েওয়ার

2

আমি সঙ্গে কাজ করতে চান exec_queryএর ActiveRecord, বর্গ, কারণ এটি বস্তুর মধ্যে রূপান্তর ক্যোয়ারী ম্যাপিং ফেরৎ, তাই এটি বস্তুর সঙ্গে পুনরুক্তি করতে খুব বাস্তব এবং উত্পাদনশীল পায় যখন বিষয় কাঁচা এসকিউএল হয়।

উদাহরণ:

values = ActiveRecord::Base.connection.exec_query("select * from clients")
p values

এবং এই সম্পূর্ণ কোয়েরিটি ফেরত দিন:

[{"id": 1, "name": "user 1"}, {"id": 2, "name": "user 2"}, {"id": 3, "name": "user 3"}]

শুধুমাত্র মানগুলির তালিকা পেতে

p values.rows

[[1, "user 1"], [2, "user 2"], [3, "user 3"]]

শুধুমাত্র ক্ষেত্রের কলামগুলি পেতে

p values.columns

["id", "name"]

0

আপনি অ্যাক্টিভেকর্ড শর্তের সাথে কাঁচা এসকিউএল মিশ্রন করতে পারেন, উদাহরণস্বরূপ যদি আপনি কোনও শর্তে কোনও ফাংশন কল করতে চান:

my_instances = MyModel.where.not(attribute_a: nil) \
  .where('crc32(attribute_b) = ?', slot) \
  .select(:id)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.