I am performing stored procedures the input option is as follows:
Declare #table varchar (20)
Set #query = 'Select * from' + #table + 'Where id = 1'
Exec sp_executesql #query
The question is can it be done in some other way without the SQL being handled as varchar?
I was thinking along the lines of something similar to the following:
Declare #varchar varchar(20)
Set #tabla = 'MyTabla'
SELECT * FROM #table
I have this code embedded in a .html.erb file:
require 'sqlite3'
# Open a SQLite 3 database file
db = SQLite3::Database.new 'file.db'
# Create a table
result = db.execute <<-SQL
CREATE TABLE numbers (
name VARCHAR(30),
val INT
);
SQL
# Insert some data into it
{ 'one' => 1, 'two' => 2 }.each do |pair|
db.execute 'insert into numbers values (?, ?)', pair
end
# Find some records
db.execute 'SELECT * FROM numbers' do |row|
p row
end
As you can see the code is creating a database, then create a table, etc..
My problem: I don't know where the file "file.db" is created. I have searched for it on the whole Windows, but I cannot find it.
NOTE 1: it seems the file and the table are being created, because if I request for the same .html.erb, I get Error: the table 'numbers' already exists.
NOTE 2: I know this is not the best place to add the ruby code related to a database. I know I should write it on the controller.
Here it is the full code:
<%
require 'sqlite3'
# Open a SQLite 3 database file
db = SQLite3::Database.new 'development.sqlite3'
# Create a table
result = db.execute <<-SQL
CREATE TABLE numbers (
name VARCHAR(30),
val INT
);
SQL
# Insert some data into it
{ 'one' => 1, 'two' => 2 }.each do |pair|
db.execute 'insert into numbers values (?, ?)', pair
end
# Find some records
db.execute 'SELECT * FROM numbers' do |row|
p row
end
%>
<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>
Look for file.db. SQL lite is a truly light database. To view the tables and records read following:
https://www.tutorialspoint.com/sqlite/sqlite_create_database.htm
I made a Select using Active Record with a lot of Joins. This resulted in duplicate values. After the select function there's the distinct function with value :id. But that didn't work!
Here's the code:
def join_query
<<-SQL
LEFT JOIN orders on orders.purchase_id = purchases.id
LEFT JOIN products on products.id = orders.complete_product_id
SQL
end
def select_query
<<-SQL
purchases.*,
products.reference_code as products_reference_code
SQL
end
result = Purchase.joins(join_query)
.select(select_query)
.distinct(:id)
Of course, neither distinct! or uniq functions worked. The distinct! returned a error from "ActiveRecord::ImmutableRelation" that I don't know what means.
To fix this I did a hack, converting the ActiveRecord_Relation object to an Array and I used the uniq function of Ruby.
What's going on here?
try this out:
def select_query
<<-SQL
DISTINCT ON (purchases.id) purchases.id,
products.reference_code as products_reference_code
SQL
end
add more comma separated column names in select clause
Purchase.select(select_query).joins(join_query)
I have a Stored Procedure that outputs totals from an eForm table. I want to use this Stored Procedure to pull out data from other eForm tables and so want to replace the eForm table name in the From clause with a parameter. I've read the other questions, but can't find one that helps with using a parameter in From. The code for this Stored Procedure looks like this -
IF OBJECT_ID ('sp_SelectEformMonthlyTotals') IS NOT NULL
DROP PROCEDURE sp_SelectEformMonthlyTotals
GO
CREATE PROCEDURE sp_SelectEformMonthlyTotals #EFORMNAME VARCHAR (200) = ''
AS
CREATE TABLE #TEMP (EFORMNAME VARCHAR (200))
INSERT INTO #TEMP
EXEC sp_UpdateEForm #EFORMNAME
SELECT ....
FROM #EFORMNAME T1 INNER JOIN FLODS_CASE_ENQUIRY_F00 T2 ON T1.EFORM_CASE_ENQUIRY_ID = T2.CASE_ENQUIRY_ID
WHERE T2.CREATED_DT >= '2012-04-02'
GROUP BY MONTH(T2.CREATED_DT), YEAR(T2.CREATED_DT)) T3
ORDER BY YEAR, MONTH_NUMBER
DROP TABLE #TEMP
This is the latest attempt of many and now includes a second Stored Procedure called sp_UpdateEForm -
IF OBJECT_ID ('sp_UpdateEForm') IS NOT NULL
DROP PROCEDURE sp_UpdateEForm
GO
CREATE PROCEDURE sp_UpdateEForm #EFORMNAME VARCHAR (200) = ''
AS
UPDATE FRANCIS
SET eFormName = #EFORMNAME
I created the Francis table to hold the eFormName. I can see that I need to set the value of #EFORMNAME before sp_SelectEformMonthlyTotals can complete, but I just can't seem to find a way of doing this.
Thanks.
Frank
You only need to use a dynamic query for this;
CREATE PROCEDURE sp_SelectEformMonthlyTotals #EFORMNAME VARCHAR (200) = ''
AS
CREATE TABLE #TEMP (EFORMNAME VARCHAR (200))
INSERT INTO #TEMP
EXEC sp_UpdateEForm #EFORMNAME
DECLARE #sSQL AS VARCHAR(2000), #DateCreated as varchar(10)
SET #DateCreated = '2012-04-02'
SET #sSQL = 'SELECT .... '
SET #sSQL = #sSQL + ' FROM ' + #EFORMNAME + ' T1 INNER JOIN FLODS_CASE_ENQUIRY_F00 T2 ON T1.EFORM_CASE_ENQUIRY_ID = T2.CASE_ENQUIRY_ID '
SET #sSQL = #sSQL + ' WHERE T2.CREATED_DT >= '' + #DateCreated + '''
SET #sSQL = #sSQL + ' GROUP BY MONTH(T2.CREATED_DT), YEAR(T2.CREATED_DT)) T3'
SET #sSQL = #sSQL + ' ORDER BY YEAR, MONTH_NUMBER'
exec #sSQL
DROP TABLE #TEMP
I have 4 tables:
key: id, name
project: id, name
project_key: id, key_id, project_id
project_report: id, status, project_id, key_id
project_c_report: id, status, project_id, key_id, c_id
I want to produce a report using those tables:
The output should be:
Key.name, project_report.status, project_c_report.status
I was able to do this by getting all the keys from a project, and loop over them
array = []
project.keys.each do |k|
p = ProjectReport.where(keyword_id: k, project_id: p.id).map(&:status)
c = ProjectCReport.where(keyword_id: k, project_id: p.id, c_id:1).map(&:status)
array << {name: k.name, pr: p, pcr: c}
end
array
The problem is that I am doing a lot of selects and everything is slow, can someone help me please with a better way of doing this.
Thank you
First, create a function in your DataBase. This is just a brief example, and also its done in PostgreSQL but shouldnt difer much
from MySQL, SQLServer, etc
Function get_myreport(key_id integer, project_id integer [As many params as you'd like the function to get))
pProject ALIAS FOR $1;
pKey ALIAS FOR $2;
BEGIN
CREATE TEMP TABLE IF NOT EXISTS tmp_project_report(id integer, project_name character varying, *All the values you want to see in the report);
TRUNCATE tmp_project_report;
INSERT INTO tmp_project_report(all the columns)
SELECT a.table1_fields, b.table2_fields, c.table3_fields, d.table4_fields, e.table5_fields
FROM table1 a, table2 b, table3 c, table4 d, table5 e
WHERE
a.key = pKey
AND b.project_key = pProject
END;
Then, in your controller's method you call the up the function like this
myFunction = ActiveRecord:Base.connection.execute = "Select get_myreport("param1, param2, etc...")
You will have to make a model where you put all the fields that are on the temp_table you've made, and also you will set the temp_table as the self.table_name
Then, in your view, you'd only have to iterate on your collection and display the values accordingly
#report = TempTable.all
<% #report.each_do |report| %>
<% report.value1 %>
<% etc... %>
<% end %>
Figure out the database query, then query the database directly from your model:
def records
connection = ActiveRecord::Base.connection
records = connection.select %Q {
SELECT key.name, project_report.status, project_c_report.status
FROM ...
JOIN ...
;
}
records
end
Here is something you can try if you choose to keep this within Rails (note that the following query is untested and is shown for concept only):
report_data = Project.joins(project_key: :key)
.joins('left join project_reports on project_keys.project_id = project_reports.project_id and project_keys.key_id = project_reports.key_id
left join project_c_reports on project_keys.project_id = project_c_reports.project_id and project_keys.key_id = project_c_reports.key_id')
.where('project_c_reports.c_id = ?', 1)
.select('projects.name, project_reports.status as report_status, project_c_reports.status as c_report_status')
This should give you an array of Project objects each including the selected three attributes name, report_status, c_report_status. To get these values in an array of these three elements you could do:
report_data.map { |p| [ p.name, p.report_status, p.c_report_status ] }
The type of join for the query depends on your requirement. Given the index are in place the query should be better compared to how it looks in code!