TCL List or variables in SQL - sql

I am running into an issue trying to use a list in with orasql. Is there another way to do it? I know I could loop through using foreach and set the value to a string variable but I think it would take a lot longer with all of those little db pulls. I could also run one query but I am no DBM and I can't seem to get the query time down, it's a lot more complex than what I am laying out here and I need users to pull it as quickly as possible.
How can I do something like this:
orasql $DB(db) "select this from this_table"
orafetch $DB(db) {
lappend list1 #1
}
orasql $DB(db) "select that from that_table where this in ($list1)"
orafetch $DB(db) {
lappend that #1
}

Is this what you are trying to do?
select that
from that_table
where this in (select this from this_table);

Related

Groovy SQL Multiple ResultSets

I am calling a stored procedure from my Groovy code. The stored proc looks like this
SELECT * FROM blahblahblah
SELECT * FROM suchAndsuch
So basically, two SELECT statements and therefore two ResultSets.
sql.eachRow("dbo.testing 'param1'"){ rs ->
println rs
}
This works fine for a single ResultSet. How can I get the second one (or an arbitrary number of ResultSets for that matter).
You would need callWithAllRows() or its variant.
The return type of this method is List<List<GroovyRowResult>>.
Use this when calling a stored procedure that utilizes both output
parameters and returns multiple ResultSets.
This question is kind of old, but I will answer since I came across the same requirement recently and it maybe useful for future reference for me and others.
I'm working on a Spring application with SphinxSearch. When you run a query in sphinx, you get results, you need to run a second query to get the metadata for number of records etc...
// the query
String query = """
SELECT * FROM INDEX_NAME WHERE MATCH('SEARCHTERM')
LIMIT 0,25 OPTION MAX_MATCHES=25;
SHOW META LIKE 'total_found';
"""
// create an instance of our groovy sql (sphinx doesn't use a username or password, jdbc url is all we need)
// connection can be created from java, don't have to use groovy for it
Sql sql = Sql.newInstance('jdbc:mysql://127.0.0.1:9306/?characterEncoding=utf8&maxAllowedPacket=512000&allowMultiQueries=true','sphinx','sphinx123','com.mysql.jdbc.Driver')
// create a prepared statement so we can execute multiple resultsets
PreparedStatement ps = sql.getConnection().prepareStatement(query)
// execute the prepared statement
ps.execute()
// get the first result set and pass to GroovyResultSetExtension
GroovyResultSetExtension rs1 = new GroovyResultSetExtension(ps.getResultSet())
rs1.eachRow {
println it
}
// call getMoreResults on the prepared statement to activate the 2nd set of results
ps.getMoreResults()
// get the second result set and pass to GroovyResultSetExtension
GroovyResultSetExtension rs2 = new GroovyResultSetExtension(ps.getResultSet())
rs2.eachRow {
println it
}
Just some test code, this needs some improving on. You can loop the result sets and do whatever processing...
Comments should be self-explanatory, hope it helps others in the future!

Returning one cell from Codeigniter Query

I want to query a table and only need one cell returned. Right now the only way I can think to do it is:
$query = $this->db->query('SELECT id FROM crops WHERE name = "wheat"');
if ($query->num_rows() > 0) {
$row = $query->row();
$crop_id = $row->id;
}
What I want is, since I'm select 'id' anyway, for that to be the result. IE: $query = 'cropId'.
Any ideas? Is this even possible?
Of course it's possible. Just use AND in your query:
$query = $this->db->query('SELECT id FROM crops WHERE name = "wheat" AND id = {$cropId}');
Or you could use the raw power of the provided Active Record class:
$this->db->select('id');
$this->db->from('crops');
$this->db->where('name','wheat');
$this->db->where('id',$cropId);
$query = $this->db->get();
If you just want the cropId from the whole column:
foreach ($query->result()->id as $cropId)
{
echo $cropId;
}
Try this out, I'm not sure if it will work:
$cropId = $query->first_row()->id;
Note that you want to swap your quotes around: use " for your PHP strings, and ' for your SQL strings. First of all, it would not be compatible with PostgreSQL and other database systems that check such things.
Otherwise, as Christopher told you, you can test the crop identifier in your query. Only if you define a string between '...' in PHP, the variables are not going to be replaced in the strings. So he showed the wrong PHP code.
"SELECT ... $somevar ..."
will work better.
Yet, there is a security issue in writing such strings: it is very dangerous because $somevar could represent some additional SQL and completely transform your SELECT in something that you do not even want to think about. Therefore, the Active Record as mentioned by Christopher is a lot safer.

Perl DBI - transfer data between two sql servers - fetchall_arrayref

I have 2 servers: dbh1 and dbh2 where I query dbh1 and pull data via fetchall_arrayref method. Once I execute the query, I want to insert the output from dbh1 into a temp table on server dbh2.
I am able to establish access to both servers at the same time and am able to pull data from both.
1. I pull data from dbh1:
while($row = shift(#$rowcache) || shift(#{$rowcache=$sth1->fetchall_arrayref(undef, $max_rows)})) {
#call to sub insert2tempData
&insert2tempData(values #{$row});
}
2. Then on dbh2 I have an insert query:
INSERT INTO ##population (someid, Type, anotherid)
VALUES ('123123', 'blah', '634234');
Question:
How can I insert the bulk result of the fetchall_arrayref from dbh1 into the temp table on server dbh2 (without looping through individual records)?
Ok - so i was able to resolve this issue and was able to implement the following code:
my $max_rows = 38;
my $rowcache = [];
my $sum = 0;
if($fldnames eq "ALL"){ $fldnames = join(',', #{ $sth1->{NAME} });}
my $ins = $dbh2->prepare("insert into $database2.dbo.$tblname2 ($fldnames) values $fldvalues");
my $fetch_tuple_sub = sub { shift(#$rowcache) || shift(#{$rowcache=$sth1->fetchall_arrayref(undef, $max_rows)}) };
my #tuple_status;
my $rc;
$rc = $ins->execute_for_fetch($fetch_tuple_sub, \#tuple_status);
my #errors = grep { ref $_ } #tuple_status;
The transfer works but it is still slower than if I were to transfer data manually through SQL Server export/import wizard . The issue that i notice is that the data flows row by row into the destination and I was wondering if it is possible to increase the bulk transfer size. It downloads the data extremely fast, but when i combine download and upload then the speeds decreases dramatically and it takes up to 10 minutes to transfer a 5000 row table between servers.
It would be better if you said what your goal was (speed?) rather than asking a specific question on avoiding looping.
For a Perl/DBI way:
Look at DBI's execute_array and execute_for_fetch however as you've not told us which DBD you are using it is impossible to say more. Not all DBDs support bulk insert and when they don't DBI emulates it. DBD::Oracle does and DBD::ODBC does (in recent versions see odbc_array_operations) but in the latter it is off by default.
You didn't mention which version of SQL Server you are using. First, I would look into the "BULK INSERT" support of that version.
You also didn't mention how many rows are involved. I'll assume that they fit into memory, otherwise a bulk insert won't work.
From there it's up to you to translate the output of fetchall_arrayref into the syntax needed for the "BULK INSERT" operation.

Does CDbcommand method queryAll() in yii return indexed entries only?

I am trying to retrieve data from a simple mySql table tbl_u_type which has just two columns, 'tid' and 'type'.
I want to use a direct SQL query instead of the Model logic. I used:
$command = Yii::app()->db->createCommand();
$userArray = $command->select('type')->from('tbl_u_type')->queryAll();
return $userArray;
But in the dropdown list it automatically shows an index number along with the required entry. Is there any way I can avoid the index number?
To make an array of data usable in a dropdown, use the CHtml::listData() method. If I understand the question right, this should get you going. Something like this:
$command = Yii::app()->db->createCommand();
$userArray = $command->select('tid, type')->from('tbl_u_type')->queryAll();
echo CHtml::dropdownlist('my_dropdown','',CHtml::listData($userArray,'tid','type'));
You can also do this with the Model if you have one set up for the tbl_u_type table:
$users = UType::model()->findall();
echo CHtml::dropdownlist('my_dropdown','',CHtml::listData($users ,'tid','type'));
I hope that gets you on the right track. I didn't test my code here, as usual, so watch out for that. ;) Good luck!

How to access Seconds_Behind_Master from SQL

I would like to have access to the Seconds_Behind_Master field, (as returned by SHOW SLAVE STATUS) from inside a stored procedure.
I can't figure out how to get its value inside a variable. None of the usual SET/SELECT syntax seems to work.
Is there a way to do that?
Just for the record: it has turned out to be possible to open a cursor for SHOW statements. This allows to parse the output and work with it inside a stored procedure.
From what I see in the recent docs and MySQL Bug#37187 there does not seem to be any way but SHOW SLAVE STATUS to get to this information.
PHP can grab all the fields of the show slave status into a hashmap, like this:
$db = new pdo(
"mysql:host=your_database_hostname;dbname=your_database_name",
'your_username', 'your_password');
$sql = 'show slave status';
$query = $db->query($sql);
$res = $query->fetchall();
foreach($res as $item){
print ">" . $item["Seconds_Behind_Master"];
}
Which prints 0 seconds because everything is up to date:
>0
I tried for an hour to create a stored procedure to do this. I recommend you don't waste your time.