I am trying to insert values from one table to another one using the following insert sql query
INSERT INTO [dbo].[table2]
SELECT Exec [StoredProcedure],
[Column1]
,[Column2]
FROM [dbo].[table1]
[table2] has the following columns:
RecNo, <-- INT
Column1, <--VARCHAR(50)
Column2 <--VARCHAR(50)
[StoredProcedure] main purpose is that every time a new row to be inserted in table2 it selects the maximum value from RecNo from table2 and adds 1 to that number to create the next number (sequential).
Here is the script for the stored procedure .
GO
ALTER PROCEDURE [dbo].[UpdateRcnoNumbers]
#MaxRcno INT OUTPUT
AS
BEGIN
SELECT #MaxRcno=MAX(Recno) FROM [table2]
SELECT #MaxRcno=#MaxRcno+1
RETURN #MaxRcno
END
But I am getting an error and I am not able to call the stored procedure ? Any suggestion please .
Thank you in advance
You should write a function for this purpose , read here
The problem is, Stored Procedures don't really return output directly. They can execute select statements inside the script, but have no return value.
MySQL calls stored procedures via CALL StoredProcedureName(); And you cannot direct that output to anything, as they don't return anything (unlike a function).
Here
MySQL Call Command
Related
Aggregate functions are working for my on command line and in my SQL client, but when I run those very same aggregate functions for use in setting a variable inside a stored procedure, I get duplicate values - the same number of values for multiple rows, but all values are the same.
Say I have a table `table_name`:
|test_field | target_field|
|----------------:|:------------|
|"test_value" |1 |
|"test_value" |2 |
|"not_test_value" |3 |
|"test_value" |4 |
The aggregate function works as expected in regular SQL query:
SET #array_value := "";
SELECT GROUP_CONCAT(target_field) INTO #array_value
FROM `table_name`
WHERE `test_field` = 'test_value';
Where I get the result:
"1,2,4"
However, when I use same syntax inside a stored procedure, I get very different results:
"4,4,4"
Note that this stored procedure is triggered on an update of the same table:
CREATE TRIGGER `cacheAggregate`
AFTER INSERT ON `table_name`
FOR EACH ROW
BEGIN
CALL storedProcedureName (
NEW.target_field
);
END
...which calls the following stored procedure:
CREATE PROCEDURE `storedProcedureName `(
IN `target_field` VARCHAR
)
BEGIN
SET #answer_array := '';
SELECT GROUP_CONCAT(target_field) INTO #answer_array
FROM `table_name`
WHERE `test_field` = "test_value";
INSERT INTO CACHE_TABLE (`answers_array`, `fk_target_field`)
VALUES(#answer_array, target_field);
END
When I insert a value into the table, the trigger fires, calls the stored procedure, but the issue presents itself - #answer_array is wrong, consisting of a an array of the correct length, where each value is always the last value entered into the table.
IE, If I run this query:
INSERT INTO `table_name` (`test_field`,`target_field`) VALUES ("test_value", 5);
I would expect it to be stored as:
"1,2,4,5"
However, what is actually being returned is:
"5,5,5,5"
My guess is that the stored procedure is using some kind of cursor/pointer which breaks the aggregate function, but I had trouble finding anyone who had the same issue.
UPDATE/RESOLVED
While trying to reproduce this with the modified example code, I found my issue.
I'm leaving this here in case it helps anyone out in the future.
The issue was a naming collision. The parameter name for my stored procedure was the same as the target_field of my table, so the SELECT statement was using the stored procedure parameter as opposed to the table field. Since the value passed to the stored procedure the last updated value sent by the trigger, it was replicated the number of the resultant rows.
It would be the same if I used a literal in a select statement that returned multiple rows, EG:
SELECT GROUP_CONCAT("String Literal") INTO #answer_array
FROM `table_name`
WHERE `test_field` = "test_value";
...would produce the result:
"String Literal,String Literal,String Literal,String Literal"
The solution was to either explicitly set the table name in the GROUP_CONCAT argument:
SELECT GROUP_CONCAT(tn.target_field) INTO #answer_array
FROM `table_name` tn
WHERE `test_field` = "test_value";
-or-
...you could just change the name of the passed IN parameter in the stored procedure:
CREATE PROCEDURE `storedProcedureName `(
IN `sp_target_field` VARCHAR
)
...
I'm having a problem with my sql query. I need to insert a data that needs to be checked first if it is existing or not. If the data is existing the sql query must return it, if not insert and return it. I already google it but the result is not quite suitable to my problem. I already read this.
Check if a row exists, otherwise insert
How to 'insert if not exists' in MySQL?
Here is a query that' I'm thinking.
INSERT INTO #tablename(#field, #conditional_field, #field, #conditional_field)
VALUES(
"value of field"
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it),
"value of feild",
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it)
);
Please take note that the conditional field is a required field so it can't be NULL.
Your tag set is quite weird, I'm unsure you require all the technologies listed but as long as Firebird is concerned there's UPDATE OR INSERT (link) construction.
The code could be like
UPDATE OR INSERT INTO aTable
VALUES (...)
MATCHING (ID, SomeColumn)
RETURNING ID, SomeColumn
Note that this will only work for PK match, no complex logic available. If that's not an option, you could use EXECUTE BLOCK which has all the power of stored procedures but is executed as usual query. And you'll get into concurrent update error if two clients execute updates at one time.
You could split it out into 2 steps
1. run a select statement to retrieve the rows that match your valus. select count (*) will give you the number of rows
2. If zero rows found, then run the insert to add the new values.
Alternatively, you could create a unique index form all your columns. If you try to insert a row where all the values exist, an error will be returned. You could then run a select statement to get the ID for this existing row. Otherwise, the insert will work.
You can check with if exists(select count(*) from #tablename) to see if there is data, but with insert into you need to insert data for all columns, so if there is only #field missing, you cant insert values with insert into, you will need to update the table and go with a little different method. And im not sure, why do you check every row? You know for every row what is missing? Are you comparing with some other table?
You can achieve it using MySQL stored procedure
Sample MySQL stored procedure
CREATE TABLE MyTable
(`ID` int, `ConditionField` varchar(10))
;
INSERT INTO MyTable
(`ID`, `ConditionField`)
VALUES
(1, 'Condition1'),
(1, 'Condition2')
;
CREATE PROCEDURE simpleproc (IN identifier INT,ConditionData varchar(10))
BEGIN
IF (SELECT ID FROM MyTable WHERE `ConditionField`=ConditionData) THEN
BEGIN
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
ELSE
BEGIN
INSERT INTO MyTable VALUES (identifier,ConditionData);
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
END IF;
END//
To Call stored procedure
CALL simpleproc(3,'Condition3');
DEMO
I want to do something like this (pseudocode):
SELECT IF (I don't get NULL, "pass", null)
FROM(
INSERT INTO table VALUES (value)
)
If the insert is successful, it will not return anything, so this query returns null. If the insert is successful, I will get "pass" instead of a value.
I don't know how to do this. I'm thinking a stored procedure can do it, but I also think that it's not necessary.
Edit:
I've so far tried this, though:
INSERT INTO `permissions` VALUES (7,"test",null);
SELECT IF(`p_id` IS NOT NULL, "pass", null ) `p_id`
FROM `permissions`
WHERE `p_id` = 7;
Where 7 is user-defined. This one works as I want it to. It's not a stored procedure, but it's two queries. I want to know if it's possible to do this with just one query?
A MySQL INSERT statement doesn't return a resultset; so it can't be used a row source for a query. If the INSERT statement fails, it will throw an error.
To return a resultset, a separate SELECT statement would need to be executed.
These two statements could be executed in the context of a stored procedure, if the goal is to execute a single database call.
EDIT:
Q: I want to know if it's possible to do this with just one query?
A: No, it's not possible with just one statement. You'd need two statements: an INSERT statement (to perform the insert operation) and an SELECT statement (to return a result).
To do this in a single database call, you'd need a MySQL stored program that performs the two statements: first, the INSERT, and catch errors thrown (with a CONTINUE HANDLER), and then a SELECT to return a resultset.
It's not clear why you need a resultset that returns a column containing 'PASS' or NULL.
The normative pattern would be to run the INSERT statement, check to see whether it threw an error, and/or check "affected rows" using function available in the client library, and/or run a separate SELECT statement to retrieve the value from the MySQL ROW_COUNT() function, e.g.
INSERT INTO mytable (mycol) VALUES ('myval') ;
SELECT IF(ROW_COUNT(),'PASS',NULL) ;
(To do this within a stored procedure, you'd need to define a CONTINUE HANDLER in the procedure to "catch" errors from the INSERT so that the procedure will continue running (rather than throwing an error) so the SELECT statement will be run.)
Is this what you wanted ??
INSERT INTO table1
(
column1,
column2,
)
VALUES
(
(
SELECT column
FROM table2
JOIN table3 ON condition
),
(
"a string"
),
);
See the link here
I am using a stored procedure to insert data into two tables. But when I insert the datas the total number of rows in the first table and the second table is different, so it means that sometimes it only inserted the datas in the first table but failed to insert it in the second table. But this case should not happen in my case as the Id of the two tables is related to each other. How can I solve this problem? So that when it will insert datas in both tables or no table if an error occurs so that the number of datas are the same in both the table. My stored procedure is as follows:
Begin
insert into base_table(imgPath,store,apparelType) values (imgPath,store,apparelType);
insert into data_table(cvID,color) values
(LAST_INSERT_ID(),color);
END
To make sure that the 1st query has been successfully executed, the best way would be to add an Identity column in your base_table, then proceed as follows;
DECLARE #LAST_INSERT_ID INT
DECLARE #EXECUTION_OK char(1)
SET #EXECUTION_OK = 1
insert into base_table(imgPath,store,apparelType) values (imgPath,store,apparelType)
SELECT #LAST_INSERT_ID = SCOPE_IDENTITY()
insert into data_table(cvID,color) values (#LAST_INSERT_ID, color)
GO
If exists( Select cvID from data_table where cvID= #LAST_INSERT_ID)
Begin
#EXECUTION_OK = 0
End
SCOPE_IDENTITY: Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can also use the mysql_affected_rows() function to verify that the query has been successful.
I'm work with store procedures, supose that I've the following procedure that return a value, and this value I use in other query.
CREATE PROCEUDRE filter(IN string varchar(1000), OUT salida varchar(1000))
BEGIN
.....
END
And I want make a insert with a select query for example:
INSERT INTO otherTable
SELECT filter(concat_group(column)) , value1,value2 from mytable
GROUP BY column,value,value2;
which is the correct way to do this?
Generally, you cannot call a stored procedure in the SQL select statement. What you want is like custom scalar functions.
reference
mysql scalar function with for loop