This may or may not be a simple question.
I am looking for a way to NOT select anything from a table, but return a set of table-like data.
Basically I have a procedure that loops through a table and stores data into a variable, then displays it by the line:
SELECT #args as parents;
Is there any better way to set up a table data structure and return that whole thing? Right now I am returning a single variable with multiple (parse-needed) data.
EDIT:
To try and explain better:
What I have to do is loop through and perform a series of select statements, is there a way to 'concat' this data into a big datatable structure and then return that table?
Use a temp table
DROP TABLE IF EXISTS tmp;
CREATE TABLE tmp( --fields-- );
WHILE ( --condition-- ) DO
INSERT INTO tmp VALUES ( --fields-- );
SELECT --Statement--
END WHILE;
--do stuff--
and clean up
DROP TABLE tmp
I'm not positive for mySQL, but you should be able to use a function to return a table. I found the following on another question, which might be helpful:
CREATE FUNCTION getdepartments()
RETURNS #departments TABLE(
DNAME VARCHAR(25),
DEPTID VARCHAR(10),
DBONUS DECIMAL(7,2))
AS
BEGIN
INSERT #departments SELECT * FROM DEPARTMENT;
RETURN
END
I've done this in SQL Server, and you can do fun things like recursive functions that keep adding records to your output table, etc.
Maybe you could return a recordset like described here http://forums.mysql.com/read.php?102,50520,50626#msg-50626. Hope that this will help.
Related
Goal:
I'm trying to store the tables results of a query as a variable in a function.
I'd like to be able to do more things in this procedure referencing these tables.
I've got a scaffold function below:
DELIMITER $$
CREATE FUNCTION getRatio(treatmentA INT, treatmentB INT)
RETURNS FLOAT
BEGIN
DECLARE answer FLOAT;
DECLARE countA, countB, countABIntersection;
# Store patients of treatment A
SELECT DISTINCT patient
INTO **Variable**
FROM Treatment
WHERE TreatmentID = treatmentA;
# Store patients of treatment B
SELECT DISTINCT patient
INTO **Variable**
FROM Treatment
WHERE TreatmentID = treatmentB;
# Get Intersection of treatment B
Set answer = count(TreatmentA) * count(TreatmentB) * count(IntersectionTreatmentAB)
RETURN answer;
END $$
DELIMITER ;
If anyone can help, it would be greatly appreciated.
Thanks in advance.
You only can store or return a value from a function which MySQL have datatypes.
In short if you want to store a result set to variable you have to have a table datatype, unfortunately MySQL doesn't have such.
Solution: What you can do is, you can create temporary tables with respective columns for each result set to store(or may be in the same temp table in your case).
Do all operations on the temp table and store the result to a variable(FLOAT in you case), return the variable.
Let me know if that helps :)
-Thanks
Is it possible to get stored procedure multiple result set to temp table variable?
I wrote a stored procedure like,
Create proc test1
(
#param1 int,
#param2 int
)
as
Begin
Select Id, Name from Table1 where column1=#param1;
Select Id, Age, Address from Table2 where column1=#param2;
End
When i execute this sp it will return 2 tables(record set's).
Now, i want to get this 2 record sets to 2 temp table variables.
How can i achieve this?
I don't believe a stored procedure can return multiple result sets like you want it to. What I might suggest is to have the stored proc store the results in two global temp tables and then have the calling process (whatever is calling your stored proc) query the two global temp tables and put the results into your temp table variables.
I know this is an old question, and maybe I am misunderstanding what you want, but if you just want to take those two recordsets and put them into temp tables, couldn't you do this:
Create proc test1
(
#param1 int,
#param2 int
)
as
Begin
Select Id, Name
into #temp1
from Table1 where column1=#param1;
Select Id, Age, Address
into #temp2
from Table2 where column1=#param2;
End
now, I dont know what you're trying to achieve with this, but depending on how you're calling that sp, the #temp tables may not be accessible from outside of the sp.
I would like to get count of specific records. So my query will look like the following...
SELECT
ID,
NAME,
(SELECT...) AS UserCount // Stmt1
FROM MyTable
The issue is that, 'Stmt1' is a complex statement and it cannot be written as innerquery.
Well, I can use functions, but the statement includes 'CREATE TABLE' so I get the following error message
Cannot access temporary tables from within a function.
What is the best way to accomplish the task ?
You can use user defined table type to solve your problem.
You just create a table variable like
CREATE TYPE [dbo].[yourTypeName] AS TABLE(
[columeName1] [int] NULL,
[columeName2] [varchar](500) NULL,
[columeName3] [varchar](1000) NULL
)
GO
and you can declare this table variable in your function like
CREATE FUNCTION [dbo].[yourFunctionName]
(
#fnVariable1 INT ,
#yourTypeNameVariable yourTypeName READONLY
)
RETURNS VARCHAR(8000)
AS
BEGIN
SELECT .................
FROM #yourTypeNameVariable
WHERE ........
RETURN #r
END
On your procedure you can declare your table type like
DECLARE #yourTypeNamevaribale AS yourTypeName
And you can insert values to this table like
insert into #yourTypeNamevaribale (col,col,..)values(val,val,..)
pass this to your function like
dbo.yourFunctionName(fnVariable1 ,#yourTypeNamevaribale )
please go for this method, thank you
Yes you can not use #temp table.
As you are using SQL Server 2008, why don't you use table variable instead of #temp tables?
Give it a try.
I came across this post as I started using table variables and switched to temporary tables for performance reasons only to find temporary tables couldn't be used in a function.
I would be hesitant about using table variables especially if you are playing with large result sets, as these are held in memory. See this post...
http://totogamboa.com/2010/12/03/speed-matters-subquery-vs-table-variable-vs-temporary-table/
Other alternatives would be..
Extracting the temporary table result into another table function.
Converting the code into using sub-queries
In 99,99% of cases there is no need for any tricks with temp tables or subqueries, but use aggregation functions like COUNT, SUM or AVG in combination with OVER clause and (often) PARTITION BY.
I am not sure what the OP tried to achieve but I assume that the UserCount is somehow related to the values in MyTable. So there must be a way to join MyTable to whatever table that produces UserCount.
The most simple example is to show all users and the total number of users
SELECT id
, name
, user_count = COUNT(*) OVER()
FROM MyUsers
Ok, First off, I am not a mysql guru. Second, I did search, but saw nothing relevant related to mysql, and since my DB knowledge is limited, guessing syntactical differences between two different Database types just isn't in the cards.
I am trying to determine if a particular value already exists in a table before inserting a row. I've decided to go about this using two Stored procedures. The first:
CREATE PROCEDURE `nExists` ( n VARCHAR(255) ) BEGIN
SELECT COUNT(*) FROM (SELECT * FROM Users WHERE username=n) as T;
END
And The Second:
CREATE PROCEDURE `createUser` ( n VARCHAR(255) ) BEGIN
IF (nExists(n) = 0) THEN
INSERT INTO Users...
END IF;
END
So, as you can see, I'm attempting to call nExists from createUser. I get the error that no Function exists with the name nExists...because it's a stored procedure. I'm not clear on what the difference is, or why such a difference would be necessary, but I'm a Java dev, so maybe I'm missing some grand DB-related concept here.
Could you guys help me out by any chance?
Thanks
I'm not sure how it helped you, but...
why SELECT COUNT(*) FROM (SELECT * FROM Users WHERE username=n) and not just SELECT COUNT(*) FROM Users WHERE username=n?
Just make the user name (or whatever the primary application index is) a UNIQUE index and then there is no need to test: Just try to insert a new record. If it already exists, handle the error. If it succeeds, all is well.
It can (and should) all be one stored procedure.
Here is the updated question:
the current query is doing something like:
$sql1 = "TRUNCATE TABLE fubar";
$sql2 = "CREATE TEMPORARY TABLE IF NOT EXISTS fubar SELECT id, name FROM barfu";
The first time the method containing this is run, it generates an error message on the truncate since the table doesn't exist yet.
Is my only option to do the CREATE TABLE, run the TRUNCATE TABLE, and then fill the table? (3 separate queries)
original question was:
I've been having a hard time trying to figure out if the following is possible in MySql without having to write block sql:
CREATE TABLE fubar IF NOT EXISTS ELSE TRUNCATE TABLE fubar
If I run truncate separately before the create table, and the table doesn't exist, then I get an error message. I'm trying to eliminate that error message without having to add any more queries.
This code will be executed using PHP.
shmuel613, it would be better to update your original question rather than replying. It's best if there's a single place containing the complete question rather than having it spread out in a discussion.
Ben's answer is reasonable, except he seems to have a 'not' where he doesn't want one. Dropping the table only if it doesn't exist isn't quite right.
You will indeed need multiple statements. Either conditionally create then populate:
CREATE TEMPORARY TABLE IF NOT EXISTS fubar ( id int, name varchar(80) )
TRUNCATE TABLE fubar
INSERT INTO fubar SELECT * FROM barfu
or just drop and recreate
DROP TABLE IF EXISTS fubar
CREATE TEMPORARY TABLE fubar SELECT id, name FROM barfu
With pure SQL those are your two real classes of solutions. I like the second better.
(With a stored procedure you could reduce it to a single statement. Something like: TruncateAndPopulate(fubar) But by the time you write the code for TruncateAndPopulate() you'll spend more time than just using the SQL above.)
You could do the truncate after the 'create if not exists'.
That way it will always exist... and always be empty at that point.
CREATE TABLE fubar IF NOT EXISTS
TRUNCATE TABLE fubar
execute any query if table exists.
Usage: call Edit_table(database-name,table-name,query-string);
Procedure will check for existence of table-name under database-name and will execute query-string if it exists.
Following is the stored procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `Edit_table` $$
CREATE PROCEDURE `Edit_table` (in_db_nm varchar(20), in_tbl_nm varchar(20), in_your_query varchar(200))
DETERMINISTIC
BEGIN
DECLARE var_table_count INT;
select count(*) INTO #var_table_count from information_schema.TABLES where TABLE_NAME=in_tbl_nm and TABLE_SCHEMA=in_db_nm;
IF (#var_table_count > 0) THEN
SET #in_your_query = in_your_query;
#SELECT #in_your_query;
PREPARE my_query FROM #in_your_query;
EXECUTE my_query;
ELSE
select "Table Not Found";
END IF;
END $$
DELIMITER ;
More on Mysql
how about:
DROP TABLE IF EXISTS fubar;
CREATE TABLE fubar;
Or did you mean you just want to do it with a single query?
OK then, not bad. To be more specific, the current query is doing something like:
$sql1 = "TRUNCATE TABLE fubar";
$sql2 = "CREATE TEMPORARY TABLE IF NOT EXISTS fubar SELECT id, name FROM barfu";
The first time the method containing this is run, it generates an error message on the truncate since the table doesn't exist yet.
Is my only option to do the "CREATE TABLE", run the "TRUNCATE TABLE", and then fill the table? (3 separate queries)
PS - thanks for responding so quickly!
If you're using PHP, use mysql_list_tables to check that the table exists before TRUNCATE it.