Msg 2714, Level 16, State 1, Procedure QOTD, Line 12 There is already an object named '#tmpID3' in the database.
ALTER PROCEDURE QOTD (#source INT) AS
BEGIN
IF #source = 1
SELECT ID INTO #tmpID3 FROM tbl1
ELSE
SELECT ID INTO #tmpID3 FROM tbl2
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END
Msg 2714, Level 16, State 1, Procedure QOTD, Line 7 There is already an object named '#tmpID3' in the database. – jesvin Nov 19 at 5:37
while adding this i am getting the error
You are seeing a parser error when trying to create your procedure. The temp table does not yet exist but the parser thinks it does.
Have a look at my answer to this question: There is already an object named '#columntable' in the database.
I originally thought, as others who have answered your question, that you would get this error because you were not explicitly dropping the temp table at the end of you procedure. However, as crokusek first pointed out in his comment:
local temp tables are auto deleted at the end of the procedure in
which they are created
So I tried creating your procedure in my SQL Server 2008 instance and got the same error.
Changing the procedure to use different temp table names, as shown below, avoids the problem and proves the temp tables are dropped after the procedure ends.
CREATE TABLE tbl1 ( ID INT )
GO
CREATE TABLE tbl2 ( ID INT )
GO
INSERT INTO tbl1(ID) VALUES (1),(2),(3)
INSERT INTO tbl2(ID) VALUES (4),(5),(6)
GO
CREATE PROCEDURE QOTD ( #source INT )
AS
SET NOCOUNT ON
BEGIN
IF #source = 1
BEGIN
SELECT ID INTO #tmpID13 FROM tbl1
SELECT ID FROM #tmpID13
END
ELSE
BEGIN
SELECT ID INTO #tmpID23 FROM tbl2
SELECT ID FROM #tmpID23
END
END
GO
EXEC QOTD 1
EXEC QOTD 2
Output:
ID
-----------
1
2
3
ID
-----------
4
5
6
It's already there. If you're creating this table as part of a regularly running script, add a DROP TABLE #tmpID3 at the start.
temp tables are single threaded (ie the server can do nothing else while creating it). If you're using it often, consider table variables instead.
Start procedure QOTD with:
Drop Table #tmpID3
Objects have to have unique names across the database. SQL Server handles the uniqueness of temporary table names. However, if there are supplementary objects, such as separately created primary keys, it is possible for collisions to occur when two users attempt to create the table at the same time.
The error message you cite has an object with ID in its name, so I am guessing this is the situation you find yourself in. Andy Novick has written a note on this topic, explaining why it might happen and giving a couple of workarounds. Check it out.
Have a look at Check If Temporary Table Exists
EDIT How to check for the temp table and drop it if it exists
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
BEGIN
DROP TABLE #TEMP
END
EDIT 2 It would seem that the 2 select into's are conflicting with each other. Creating the table before hand works though. Something like
ALTER PROCEDURE QOTD (#source INT)
AS
BEGIN
IF OBJECT_ID('tempdb..#tmpID3') IS NOT NULL
BEGIN
DROP TABLE #tmpID3
END
CREATE TABLE #tmpID3(
ID INT
)
IF #source = 1
BEGIN
INSERT INTO #tmpID3 SELECT ID FROM tbl1
END
ELSE
BEGIN
INSERT INTO #tmpID3 SELECT ID FROM tbl2
END
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END
EDIT 3 the temp table is not required in this instance. A simple if will do
Something like
ALTER PROCEDURE QOTD (#source INT)
AS
BEGIN
IF #source = 1
BEGIN
SELECT ID FROM tbl1
END
ELSE
BEGIN
SELECT ID FROM tbl2
END
END
I had exactly the same issue, see my answer here:There is already an object named '#columntable' in the database
The solution in this case seems to be to first create the table, then add the rows. This way the parser does not complain (as this is a known parser issue).
ALTER PROCEDURE QOTD (#source INT) AS
BEGIN
-- Create the table without having to declare any column types or sizes
SELECT TOP 0 ID INTO #tmpID3 FROM tbl1
-- Prevent IDENTITY_INSERT error
SET IDENTITY_INSERT #tmpID3 ON
-- Add the actual rows required
IF #source = 1
INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl1
ELSE
INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl2
SET IDENTITY_INSERT #tmpID3 OFF
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END
Related
I wrote store procedure in mysql. Step were followed this website http://www.mysqltutorial.org/mysql-cursor/
But it doesn't work. Here is code
DELIMITER $$
USE `hr`$$
DROP PROCEDURE IF EXISTS `at_getShift`$$
CREATE DEFINER=`root`#`%` PROCEDURE `at_getShift`()
BEGIN
DECLARE finished BOOLEAN DEFAULT FALSE;
DECLARE employeeID VARCHAR(255);-- Default "";
-- declare cursor for employee email
DECLARE hrEmployee CURSOR FOR SELECT EmployeeID FROM h_employees WHERE EmployeeID IN ('100013', '100014');
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = TRUE;
DROP TABLE IF EXISTS temp;
CREATE TABLE IF NOT EXISTS temp(
`Code` VARCHAR(255)
);
OPEN hrEmployee;
get_employee: LOOP
FETCH hrEmployee INTO employeeID;
INSERT INTO temp(`Code`) VALUE (employeeID);
-- If no any row, leave loop
IF finished THEN
INSERT INTO temp(`Code`) VALUE ("112");
CLOSE hrEmployee;
LEAVE get_employee;
END IF;
-- insert temp
INSERT INTO temp(`Code`) VALUE ("111");
END LOOP get_employee;
SELECT * FROM temp;
END$$
DELIMITER ;
Execute: CALL at_getShift();
Result is:
2 rows in temp table ( 1 null, 1 is 112)
Please kindly help me to resolve this trouble.
In a SQL statement in MySQL stored program, the references to procedure variables take precedence over references to columns.
That is, when an identifier in a SQL statement matches a procedure variable, the SQL statement references the procedure variable.
References that are qualified with the table name or table alias reference columns from the table, even when there is a procedure variable with the same name.
Demonstration:
CREATE TABLE emp (id INT);
INSERT INTO emp (id) VALUES (101),(102);
DELIMITER $$
CREATE PROCEDURE foo()
BEGIN
DECLARE id INT DEFAULT 3;
-- this query returns 3 for all rows in emp
-- because "id" is a reference to the procedure variable
SELECT id FROM emp WHERE id = 3;
-- this query returns no rows
-- because "id" is a reference to the procedure variable
SELECT id FROM emp WHERE id = 101;
-- this query references columns in the table because
-- references to "id" are qualified
SELECT t.id FROM emp t WHERE t.id = 101;
END$$
DELIMITER ;
CALL foo;
The first query returns value of procedure variable for all rows from emp
id
-----
3
3
second query returns no rows
id
-----
third query returns references "id" column in table:
id
-----
101
The takeaway are two "best practices":
qualify all column references in a SQL statement in a procedure
and
procedure variable names should differ from names of columns, the usual pattern is to use a distinctive prefix on variables. As a trivial example: v_id, v_name, etc.
Both of these practices make it easier for a human reader to decipher a procedure.
Distinctive naming of procedure variables does reduce the chances of collisions, but does not invalidate the "best practice" of qualifying all column references in SQL statements. Both of those serve to make the author's intent more clear to the human reader.
EDIT:
I attempted to answer the question I thought you were asking... "Why is my procedure not doing what I expect it to?".
Beyond the answer to the question you asked... the operation that your procedure appears to be performing (populating a temporary table with a set of rows) that operation could be performed much faster and more efficiently by processing the rows as a set, rather than issuing painfully inefficient individual insert statements for each row. In terms of performance, a cursor loop processing RBAR (row-by-agonizing-row) is going to eat your lunch. And your lunch box.
DELIMITER $$
CREATE PROCEDURE `at_getShift_faster`()
BEGIN
-- ignore warning message when dropping a table that does not exist
DECLARE CONTINUE HANDLER FOR 1305 BEGIN END;
DROP TABLE IF EXISTS temp;
CREATE TABLE IF NOT EXISTS temp(`Code` VARCHAR(255));
INSERT INTO temp (`Code`)
SELECT h.EmployeeID
FROM h_employees h
WHERE h.EmployeeID IN ('100013', '100014')
;
SELECT * FROM temp;
END$$
DELIMITER ;
I´m working in an application that creates a simulated population database. I´m trying to write a stored procedure that creates a temporary table internally, add rows and then fetch this resultset as procedure result .
I wrote a basic code that only add 3 lines to a temp table for a test, but still not working
[EDITED]: phpmyadmin return ad non-specific compilation error #1064 you have an error in yor sql statement sintax....
[EDITED2]:
I haven´t found exactly what error is, but changing the "create termaporary table" line to a "create temporary table OUT_TEMP ENGINE=MEMORY as (Select * from OTHER_TABLE where 1=2)" it works.
see the code below:
DELIMITER//
create procedure GERA_POPULACAO(IN stDESCRICAO VARCHAR, IN stUSUARIO
VARCHAR, IN iID_ESPECIE int,
IN iNUM_INDIVIDUOS INT)
BEGIN
CREATE TEMPORARY TABLE OUT_TEMP( ID_INDIVIDUO int, ID_RACA int,
ID_CARACTERISTICA int,
VR_CARACTERISTICA int);
insert into OUT_TEMP values(1,1,1,1);
insert into OUT_TEMP values(1,1,1,2);
insert into OUT_TEMP values(1,1,1,3);
SELECT * from OUT_TEMP;
END//
DELIMITER;
appreciate any help
I have 3 existing tables: transactions, transaction_types, and expenses:
$> USE `mydb`;
Datebase changed.
$> SHOW TABLES;
expenses
transactions
transaction_types
After adding a stored procedure and 2 triggers on expenses that call the procedure, I'm no-longer able to insert into the table:
$> INSERT INTO `expenses` SET `date`='2013-12-22';
1109. Unknown table 'expenses' in field list
$> INSERT INTO `expenses` (`date`) VALUES('2013-12-22');
1109. Unknown table 'expenses' in field list
But I can select from the able just fine…
If I drop the triggers, I can insert into expenses again.
My 2 triggers are duplicates, 1 for update, 1 for insert:
USE `mydb`;
DELIMITER $$
DROP TRIGGER IF EXISTS `expense_updated_paid`
CREATE TRIGGER `expense_updated_paid`
AFTER UPDATE ON `expenses` FOR EACH ROW
BEGIN
CALL `expense_paid`( NEW.`id` , NEW.`date paid` , NEW.`amount`);
END$$
And the procedure:
USE `mydb`;
DROP procedure IF EXISTS `expense_paid`;
DELIMITER $$
CREATE PROCEDURE `expense_paid`(IN `expense_id` INT, IN `date` DATE, IN `amount` INT)
BEGIN
IF `expenses`.`date paid` IS NOT NULL THEN
SET #type_id = (SELECT `id` FROM `transaction_types` WHERE `name` = 'reimbursement');
INSERT INTO `transactions`
SET
`transactions`.`date` = `date`,
`transactions`.`amount` = `amount`,
`transactions`.`type_id` = #type_id,
`transactions`.`note` = `expense_id`;
END IF;
END$$
I expect MySQL to complain about something in the trigger or procedure if that's causing a problem instead of telling me the table just doesn't exist…
Now that you provided the procedure code, the answer is clear:
IF `expenses`.`date paid` IS NOT NULL THEN
The procedure has no context for expenses.*. That is, you can't use qualified column names inside the procedure when the qualifier refers to a query outside the procedure. This makes more sense if you accept that column qualifiers refer to correlation names in a given query, not to the table itself.
But the procedure does have the date input parameter, which you passed as the same value NEW.\date paid``. So change the line to the following:
IF `date` IS NOT NULL THEN
I have an application that save data into a table , say my_table.
my_table
id | name | salary
this is a data entry application and not having a centralized database.Once all data entries complete, I have to merge the databases. My plan is to export insert statements from say DB2 and append it to DB1. So i wrote a procedure as follows:
CREATE PROCEDURE insertToTable
DECLARE max_id INT DEFAULT 1
BEGIN
SELECT MAX(id) INTO max_id FROM my_table
INSERT INTO table(id,name,salary) VALUES(max_id+1,'tom',1000);
INSERT INTO table(id,name,salary) VALUES(max_id+1,'john',1500);
....//a lot of statements
END
here i just increment id of DB2 by the max(id) of DB1 to avoid conflict.It works fine.
But some databases have large number of records.I could get these insert statements with 'max_id' variable in position.Then can I execute these 'insert' statements from file inside that procedure. Or is there any better solution..
Make "Id" column auto incremental by adding sequence.
Then create a trigger that increment upon insert.
I think i need this trigger:
CREATE TRIGGER insert_test BEFORE INSERT ON table my_table
FOR EACH ROW
BEGIN
SET #max_id = select max(id) from my_table;
IF NEW.id >= #max_id THEN
NEW.id = #max_id + 1;
END IF;
END;
Thanks for your suggestion.
The following procedure gives me an error when I invoke it using the CALL statement:
CREATE DEFINER=`user`#`localhost` PROCEDURE `emp_performance`(id VARCHAR(10))
BEGIN
DROP TEMPORARY TABLE IF EXISTS performance;
CREATE TEMPORARY TABLE performance AS
SELECT time_in, time_out, day FROM attendance WHERE employee_id = id;
END
The error says "Unknown table 'performance' ".
This is my first time actually using stored procedures and I got my sources from Google. I just cant figure out what I am doing wrong.
I've tidied it up a little for you and added example code. I always keep my parameter names the same as the fields they represent but prefix with p_ which prevents issues. I do the same with variables declared in the sproc body but prefix with v_.
You can find another one of my examples here:
Generating Depth based tree from Hierarchical Data in MySQL (no CTEs)
drop procedure if exists emp_performance;
delimiter #
create procedure emp_performance
(
in p_employee_id varchar(10)
)
begin
declare v_counter int unsigned default 0;
create temporary table tmp engine=memory select time_in, time_out
from attendance where employee_id = p_employee_id;
-- do stuff with tmp...
select count(*) into v_counter from tmp;
-- output and cleanup
select * from tmp order by time_in;
drop temporary table if exists tmp;
end#
delimiter ;
call emp_performance('E123456789');
By default MySQL config variable sql_notes is set to 1.
That means that
DROP TEMPORARY TABLE IF EXISTS performance;
increments warning_count by one and you get a warning when a stored procedure finishes.
You can set sql_notes variable to 0 in my.cnf or rewrite stored procedure like that:
CREATE DEFINER=`user`#`localhost` PROCEDURE `emp_performance`(id VARCHAR(10))
BEGIN
SET ##session.sql_notes = 0;
DROP TEMPORARY TABLE IF EXISTS performance;
CREATE TEMPORARY TABLE performance AS
SELECT time_in, time_out, day FROM attendance WHERE employee_id = id;
SET ##session.sql_notes = 1;
END