Cannot access temporary tables from within a function - sql-server-2008

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

Related

Create view statement returns an empty result set

I have a table called matchresults which has five columns named mresultid, playerid, seasonmatchid, rank, ratingsearned
mresultid is the primary key and playerid and seasonmatchid are foreign keys
The problem is that when I try to create a view on this table:
DROP VIEW IF EXISTS matchresults_view;
CREATE VIEW matchresults_view AS
select mresultid, playerid, seasonmatchid
from matchresults
where id = 8 ;
The query runs but it says mysql returned an empty result set. This is not true as I should be having two tuples in the result set.
What is wrong with the query?
Well, you are creating a view. This command does not return any rows. It simply creates a view which you can think of as SQL query saved under a name, so that it is later possible to use in your queries. It will still execute the underlying SQL statement.
Now you have to query the view like below, to see what it outputs:
select * from matchresults_view

Call a Stored Procedure From a Stored Procedure and/or using COUNT

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.

User-defined Table Variables in MySQL 5.5?

I've recently moved from MSSQL to MySQL.
I would like to use a table variable (or equivalent) inside a MySQL 5.5 stored routine, to populate a dataset for an online report.
In MS SQL, I would do it this way
...
...
DECLARE #tblName TABLE
WHILE <condition>
BEGIN
Insert Row based on iteration value
END
...
...
From what I understand, I can't declare table variables in MySQL (correct me if I'm wrong) How do I implement the above logic in a MySQL stored procedure?
You could create a table or temporary table and populate it with data you need.
CREATE TABLE Syntax
You understand that limitation correctly. The MySQL user manual clearly states that user-defined variables cannot refer to a table:
http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected, or as a reserved word such as SELECT.
create temporary table tmp
(
id int unsigned not null,
name varchar(32) not null
)
engine=memory; -- change engine type if required e.g myisam/innodb
insert into tmp (id, name) select id, name from foo... ;
-- do more work...
select * from tmp order by id;
drop temporary table if exists tmp;
I think this covers it. Also, this may be helpful.

mysql procedure with custom 'table-like' output

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.

How does the WITH statement store the record set for the select query?

Consider the following SQL (SQL Server 2008) statement:
WITH MyResult AS
(
SELECT
Name,
Row_ID AS ORD
FROM Person Where Gender = #Gender
)
SELECT *
FROM MyResult
WHERE ORD > 5
Is MyResult stored in a temporary table in the tempdb? Or does it do something else?
We are optimising some queries and would lke to better understand WITH statements (internally) to help gauge performance etc.
Thanks
No, as per this MSDN article
...the CTE is a language-level
construct—meaning that SQL Server does
not internally create temp or virtual
tables...
And also, as mentioned here:
A common table expression (CTE) can be
thought of as a temporary result set
that is defined within the execution
scope of a single SELECT, INSERT,
UPDATE, DELETE, or CREATE VIEW
statement. A CTE is similar to a
derived table in that it is not stored
as an object and lasts only for the
duration of the query.