Measure cost of SELECT statement in PL/SQL - sql

I'm trying to measure how much does a select cost. Normally I would do it simply by getting the value of consistent gets before executing the statement and after, however, I'd like to wrap it in PL/SQL so that it's more generic. The problem I'm facing however, is how can I simply run a select without actually storing the result?
One of the ideas I had was to wrap it in a for loop like so
select value into getsBefore from v$sesstat ...
for dummy in (select name from my_table where city = 'XYZ') loop
i := i;
end loop;
select value into getsAfter from v$sesstat ...
But this doesn't seem like a correct approach.
I guess that I could simplify my question to - how can I SELECT something INTO <nothing>?
Any ideas or hints on how to accomplish this?
Thanks

Try : SELECT * bulk collect INTO [variable]
See this as a reference SELECT INTO Statement

Since the counters in V$SESSSTAT are absolute since a session is started there is no other way than to store a snapshot before an action and then subtract the snapshot from new one after the action is executed.
One of Tom Kyte's most used scripts is RUNSTATS meant to compare two actions performing the same thing to see which implementation is better.
You can find of the versions with description at http://betteratoracle.com/posts/12-runstats

Related

Why using cursors in PL/SQl ORACLE?

I'm a beginner at PL/SQL, and during studying the course I saw CURSOR
and I want to know why we should use it, and when?
thank you very much
When you do a SELECT and it returns more than one row you can't save the rows in a variable, so you'll have to use a CURSOR. If you are familiar with programming a CURSOR is something like an Array.
So if you do a SELECT and save the results in a variable like in the code:
SELECT id INTO v_id FROM table;
and if more than one row is returned, you cant save the rows in the variable v_id, and a TOO_MANY_ROWS Exception will be thrown.
Reference: http://www.oracle.com/technetwork/issue-archive/2013/13-mar/o23plsql-1906474.html
Also, if you've seen Oracle's FOR ... IN (SELECT ...) ... LOOP ... END LOOP statement, that's using an implicit cursor.
The reason to use the explicit cursor method is that you can do more things with the cursor, such as BULK COLLECT which can greatly improve your processing performance in many, but not all, situations. That greater control (beyond just doing BULK COLLECT) is helpful as you develop more-elaborate processes.
Good luck on your journey into Oracle. I've been using it for 14 years and am a big fan.

SQL: Update table column passed as variable

Any idea how to create this function in t-sql?
Pseudo-code:
function( #table, #table_column )
{
update #table
set #table_column = replace(#table_column,',','')
where #table_column like '%,%'
}
Ideas I've tried:
Procedures: only take readonly tables (http://technet.microsoft.com/en-us/library/ms187926.aspx)
Functions: cannot do updates...
Any suggestions? Thanks everyone!
Update: I had a database with about 40 tables, each with columns that I needed to remove special characters (i.e., ","). Although it would be nice to create a function/procedure where I could give it the name and fix the column, I decided instead (based on the comments) to just write each update out. Perhaps I was just looking for too fancy of a solution to a relatively simple problem.
The only way to do this is dynamic SQL. Unless you are writing database tools, you rarely need to do this kind of thing. Are you sure your database is designed correctly? What is the problem you are trying to solve?
Why do you need a function?
Usually functions are applied to a column inside the select list, such as SELECT MYFUNC(COL1) FROM TAB1;
This can definitely be done in a Stored Procedure with dynamic SQL. You can even look at a return value for the number of rows updated.
I guess the main question is what is your business requirements??

Operations on selected items

I want to have query like this:
SELECT
sum(data_parts.size) as size_sum,
(size_sum/2.) as half_of_size_sum
FROM
data_parts
WHERE
data_parts.some_id='1';
Of course it won't work, because there's no column named size_sum, so my question is:
Is there a way to use size_sum as a parameter in next select item?
Other than using a subquery containing your current query (see Davide's answer), I don't think there is a way to do that.
But you could always do:
SELECT
sum(data_parts.size) as size_sum,
(sum(data_parts.size)/2.) as half_of_size_sum
FROM
data_parts
WHERE
data_parts.id='1';
Postgres is smart enough to only get that sum once. Only if this query will be greatly expanded with more calculations being done on size_sum would I recommend the subquery approach. Not because it works better, but because it will be easier to read. But if the current calculation is all you need, don't bother with a subquery. It would actually be less easy to read.
yes, a (somewhat) ugly way of making the query run there is...
SELECT
SIZE_SUM,
SIZE_SUM/2 AS HALF_OF_SIZE_SUM
FROM (
SELECT
sum(data_parts.size) as size_sum)
FROM
data_parts
WHERE
data_parts.id='1') X;
But I don't think there is a way on postgre to do operations directly based on the previous select fields
No, and too unnecesary to use subselects for this, simply use SUM(data_parts.size) again.
I'm not sure whether I catch your point.
Do you want the code like this?
SELECT
sum(data_parts.size) as size_sum,
(sum(data_parts.size)/2.) as half_of_size_sum
FROM
data_parts
WHERE
data_parts.some_id='1';

SQL to search and replace in mySQL

In the process of fixing a poorly imported database with issues caused by using the wrong database encoding, or something like that.
Anyways, coming back to my question, in order to fix this issues I'm using a query of this form:
UPDATE table_name SET field_name =
replace(field_name,’search_text’,'replace_text’);
And thus, if the table I'm working on has multiple columns I have to call this query for each of the columns. And also, as there is not only one pair of things to run the find and replace on I have to call the query for each of this pairs as well.
So as you can imagine, I end up running tens of queries just to fix one table.
What I was wondering is if there is a way of either combine multiple find and replaces in one query, like, lets say, look for this set of things, and if found, replace with the corresponding pair from this other set of things.
Or if there would be a way to make a query of the form I've shown above, to run somehow recursively, for each column of a table, regardless of their name or number.
Thank you in advance for your support,
titel
Let's try and tackle each of these separately:
If the set of replacements is the same for every column in every table that you need to do this on (or there are only a couple patterns), consider creating a user-defined function that takes a varchar and returns a varchar that just calls replace(replace(#input,'search1','replace1'),'search2','replace2') nested as appropriate.
To update multiple columns at the same time you should be able to do UPDATE table_name SET field_name1 = replace(field_name1,...), field_name2 = replace(field_name2,...) or something similar.
As for running something like that for every column in every table, I'd think it would be easiest to write some code which fetches a list of columns and generates the queries to execute from that.
I don't know of a way to automatically run a search-and-replace on each column, however the problem of multiple pairs of search and replace terms in a single UPDATE query is easily solved by nesting calls to replace():
UPDATE table_name SET field_name =
replace(
replace(
replace(
field_name,
'foo',
'bar'
),
'see',
'what',
),
'I',
'mean?'
)
If you have multiple replaces of different text in the same field, I recommend that you create a table with the current values and what you want them replaced with. (Could be a temp table of some kind if this is a one-time deal; if not, make it a permanent table.) Then join to that table and do the update.
Something like:
update t1
set field1 = t2.newvalue
from table1 t1
join mycrossreferncetable t2 on t1.field1 = t2.oldvalue
Sorry didn't notice this is MySQL, the code is what I would use in SQL Server, my SQL syntax may be different but the technique would be similar.
I wrote a stored procedure that does this. I use this on a per database level, although it would be easy to abstract it to operate globally across a server.
I would just paste this inline, but it would seem that I'm too dense to figure out how to use the markdown deal, so the code is here:
http://www.anovasolutions.com/content/mysql-search-and-replace-stored-procedure

Oracle DB simple SELECT where column order matters

I am doing a simple SELECT statement in an Oracle DB and need to select the columns in a somewhat-specific order. Example:
Table A has 100 attributes, one of which is "chapter" that occurs somewhere in the order of columns in the table. I need to select the data with "chapter" first and the remaining columns after in no particular order. Essentially, my statement needs to read something like:
SELECT a.chapter, a. *the remaining columns* FROM A
Furthermore, I cannot simply type:
SELECT a.chapter, a.*
because this will select "chapter" twice.
I know the SQL statement seems simple, but if I know how to solve this problem, I can extrapolate this thought into more complicated areas. Also, let's assume that I can't just scroll over to find the "chapter" column and drag it to the beginning.
Thanks.
You should not select * in a program. As your schema evolves it will bring in things you do not know yet. Think about what happens when someone add a column with the whole book in it? The query you thought would be very cheap suddenly starts to bring in megabytes of data.
That means you have to specify every column you need.
Your best bet is just to select each column explicitly.
A quickie way to get around this would be SELECT a.chapter AS chapterCol, a.* FROM table a; This means there will be one column name chapterCol (assuming there's not a column already there named chapterCol. ;))
If your going to embed the 'SELECT *' into program code, then I would strongly recommend against doing that. As noted by the previous authors, your setting up the code to break if a column is ever added to (or removed from) the table. The simple advice is don't do it.
If your using this in development tools (viewing the data, and the like). Then, I'd recommend creating a view with the specific column order you need. Capture the output from 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS' and create a select statement for the view with the column order you need.
This is how I would build your query without having to type all the names in, but with some manual effort.
Start with "Select a.chapter"
Now perform another select on your data base as follows :
select ','|| column_name
from user_tab_cols
where table_name = your_real_table_name
and column_name <> 'CHAPTER';
now take the output from that, in a cut-and-paste manner and append it to what you started with. Now run that query. It should be what you asked for.
Ta-da!
Unless you have a very good reason to do so, you should not use SELECT * in queries. It will break your application every time the schema changes.