Active record query select_all, prepared statement - ruby-on-rails

Am trying to write a prepared statement like below :
#fofs = FileOrFolder.connection.select_all("select * from newtestdocB.file_or_folders where name like","%#{params[:search]}%")
It turns out to be a wrong query on mysql console. Does not take the variable %#{params[:search]}% value in to query
Please correct my query ...
console messages:
Parameters: {"search"=>"do", "cluster_id"=>"2", "datasetid"=>"1", "id"=>"1"}
%do% (0.2ms) select * from newtestdocB.file_or_folders where name like
ActiveRecord::StatementInvalid (Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1: select * from newtestdocB.file_or_folders where name like):

Try a placeholder ?
"select * from newtestdocB.file_or_folders where name like ?","%#{params[:search]}%"
See the question mark in the above statement which will be filled in by the params that follows the comma.
IF the above the statement doesnt work, this must work, using "+" to concatenate, beware of the space next to "like"
sql = "select * from newtestdocB.file_or_folders where name like <<space>>" + "%#{params[:search]}%"
FileOrFolder.connection.select_all(sql)

Related

Executing a SQL query with an `IN` clause from Rails code

I know precious nothing abour Rails, so please excuse my naivete about this question.
I'm trying to modify a piece of code that I got from somewhere to make it execute it for a randomly selected bunch of users. Here it goes:
users = RedshiftRecord.connection.execute(<<~SQL
select distinct user_id
from tablename
order by random()
limit 1000
SQL
).to_a
sql = 'select user_id, count(*) from tablename where user_id in (?) group by user_id'
<Library>.on_replica(:something) do
Something::SomethingElse.
connection.
exec_query(sql, users.join(',')).to_h
end
This gives me the following error:
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: ...ount(*) from tablename where user_id in (?) group by...
^
Users is an array, I know this coz I executed the following and it resulted in true:
p users.instance_of? Array
Would someone please help me execute this code? I want to execute a simple SQL query that would look like this:
select user_id, count(*) from tablename where user_id in (user1,user2,...,user1000) group by user_id
The problem here is that IN takes a list of parameters. Using a single bind IN (?) and a comma separated string will not magically turn it into a list of arguments. Thats just not how SQL works.
What you want is:
where user_id in (?, ?, ?, ...)
Where the number of binds matches the length of the array you want to pass.
The simple but hacky way to do this would be just interpolate in n number of question marks into the SQL string:
binds = Array.new(users.length, '?').join(',')
sql = <<~SQL
select user_id, count(*)
from tablename
where user_id in (#{binds)})
group by user_id'
SQL
<Library>.on_replica(:something) do
Something::SomethingElse.
connection.
exec_query(sql, users).to_h
end
But you would typically do this in a Rails app by creating a model and using the ActiveRecord query interface or using Arel to programatically create the SQL query.

is there are any alpha logic define in informix DB

i am using informix DB , i need to get records that contain alpha [A-Za-z] character on last character
what i try is :
select * from table_name
where (SUBSTR(trim(customer),-1,1)!='0' and SUBSTR(trim(customer),-1,1)!='1' and SUBSTR(trim(customer),-1,1)!='2' and SUBSTR(trim(customer),-1,1)!='3' and SUBSTR(trim(customer),-1,1)!='4' and SUBSTR(trim(customer),-1,1)!='5' and SUBSTR(trim(customer),-1,1)!='6' and SUBSTR(trim(customer),-1,1)!='7' and SUBSTR(trim(customer),-1,1)!='8' and SUBSTR(trim(customer),-1,1)!='9') or (SUBSTR(trim(customer),-1,1)=' ') or (SUBSTR(trim(customer),-1,1)='') or (customer IS NULL)
is there are any way to write where SUBSTR(trim(customer),-1,1)=alpha rather than write
SUBSTR(trim(customer),-1,1)!='0' and SUBSTR(trim(customer),-1,1)!='1' and SUBSTR(trim(customer),-1,1)!='2' and SUBSTR(trim(customer),-1,1)!='3' and SUBSTR(trim(customer),-1,1)!='4' and SUBSTR(trim(customer),-1,1)!='5' and SUBSTR(trim(customer),-1,1)!='6' and SUBSTR(trim(customer),-1,1)!='7' and SUBSTR(trim(customer),-1,1)!='8' and SUBSTR(trim(customer),-1,1)!='9'
If you have a 'recent' version of Informix (anything over 12.10 should do) you can use regex_match():
https://www.ibm.com/support/knowledgecenter/SSGU8G_14.1.0/com.ibm.dbext.doc/ids_dbxt_544.htm
Something like :
> select * from table(set{'test','test1','tesT'})
where regex_match(unnamed_col_1, '[a-zA-Z]$');
unnamed_col_1
test
tesT
2 row(s) retrieved.
>
You can use the Informix MATCHES operator, that is supported in any version.
The query would be like this:
select * from table_name
where customer matches "*[A-Za-z]"

Rails exec_query bindings ignored

I'm trying to use exec_query to run an arbitrary query, with values brought in through bindings, and am getting unexpected errors.
Running this in the console
sql = 'SELECT * FROM foobars WHERE id IN (?)'
name = 'query_name_placeholder'
binds = [FooBar.first]
ActiveRecord::Base.connection.exec_query sql, name, binds
Yields this error:
Account Load (7.9ms) SELECT "foobars".* FROM "foobars" ORDER BY "foobars"."id" ASC LIMIT 1
PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: SELECT * FROM foobars WHERE id IN (?)
^
: SELECT * FROM foobars WHERE id IN (?)
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: SELECT * FROM foobars WHERE id IN (?)
^
: SELECT * FROM accounts WHERE id IN (?)
from /Users/foo_user/.rvm/gems/ruby-2.2.4#foo_project/gems/activerecord-4.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:641:in `prepare'
It appears the binding syntax is being ignored? I've tried ... WHERE id = ? as well, but to no avail.
mu is too short got you part of the way there. For reference, here is the method's documentation: https://apidock.com/rails/ActiveRecord/ConnectionAdapters/DatabaseStatements/exec_query
He's right in that you will need to use the underlying database's binds syntax to set bind variables in the SQL string. For Oracle this is :1, :2 for PostgreSQL this is $1, $2... so that's step one.
Step two is you need to build bind objects, which are QueryAttribute objects, not just values to be passed in. This is a bit clunky, but here's an example:
binds = [ ActiveRecord::Relation::QueryAttribute.new(
"id", 6, ActiveRecord::Type::Integer.new
)]
ApplicationRecord.connection.exec_query(
'SELECT * FROM users WHERE id = $1', 'sql', binds
)
I just spent a whole day going through unit tests and source code trying to figure that out.

RuntimeError: ERROR Mrelation "tablename" does not exist

Rails - 2.3.8
Database - Postgres(9.2)
Active record query is not able to generate tablename in double quotes ie
# this ran fine
Table.find_by_sql('Select * from "Table" Limit 1')
Sql generated - Select * from "Table" Limit 1
But issue comes in,
Table.find(:first)
Sql generated - Select * from Table Limit 1 (Clearly noticed that table not in double quotes)
Active record displaying error
ActiveRecord::StatementInvalid: RuntimeError: ERROR
C42P01 Mrelation "Table" does not exist
P15 Fparse_relation.c L864
RparserOpenTable: SELECT * FROM Table LIMIT 1
I feel that postgresql adapter is not able to generate tablename in double quotes.
I never get a chance to work on Postgres. But I have a workaround solution for this. Try as follows:
table_name = '"Table"'
table_name.find(:first)
I haven't try this in my machine since I do not have the required setup. I hope it should work.

union between requests with remplacement variables in sqlplus

I have 14 fields which are similar and I search the string 'A' on each of them. I would like after that order by "position" field
-- some set in order to remove a lot of useless text
def col='col01'
select '&col' "Fieldname",
&col "value",
position
from oneTable
where &col like '%A%'
/
-- then for the second field, I only have to type two lines
def col='col02'
/
...
def col='col14'
/
Write all the fields which contains 'A'. The problem is that those field are not ordered by position.
If I use UNION between table, I cannot take advantage of the substitution variables (&col), and I have to write a bash in unix in order to make the replacement back into ksh. The problem is of course that database code have to be hard-coded in this script (connection is not easy stuff).
If I use a REFCURSOR with OPEN, I cannot group the results sets together. I have only one request and cannot make an UNION of then. (print refcursor1 union refcursor2; print refcursor1+refcursor2 raise an exception, select * from refcursor1 union select * from refcursor2, does not work also).
How can concatenate results into one big "REFCURSOR"? Or use a union between two distinct run ('/') of my request, something like holding the request while typing new definition of variables?
Thank you for any advice.
Does this answer your question ?
CREATE TABLE #containingAValueTable
(
FieldName VARCHAR(10),
FieldValue VARCHAR(1000),
position int
)
def col='col01'
INSERT INTO #containingAValueTable
(
FieldName , FieldValue, position
)
SELECT '&col' "Fieldname",
&col "value",
position
FROM yourTable
WHERE &col LIKE '%A%'
/
-- then for the second field, I only have to type two lines
def col='col02'
INSERT INTO...
/
def col='col14'
/
select * from #containingAValueTable order by postion
DROP #containingAValueTable
But I'm not totally sure about your use of the 'substitution variable' called "col" (and i only have SQL Server to test my request so I used explicit field names)
edit : Sorry for the '#' charcater, we use it so often in SQL Server for temporaries, I didn't even know it was SQL Server specific (moreover I think it's mandatory in sql server for creating temporary table). Whatever, I'm happy I could be useful to you.

Resources