What am I doing wrong in this MySQL stored procedure? - sql

I'm trying to use the following stored procedure.
DELIMITER $$
CREATE DEFINER=`root`#`localhost`
PROCEDURE `DeleteField`( IN _TABLENAME Text, IN _FIELDNAME text)
BEGIN
if exists (select * from information_schema.Columns
where table_name = _TABLENAME and column_name = _FIELDNAME)
then
alter table _TABLENAME drop column _FIELDNAME;
end if;
END
So I do Call('anytable','Anyfield') and I get the Error
Error Code:1146Table'Database._tablename'doesn't exist
This _tablename should be my parameter, not a string.
Plz some help before I hang myself, I love my life far too much.

I expect you will need to create a dynamic SQL query to do this.
An example of how to do this is at:
http://www.java2s.com/Code/SQL/Procedure-Function/Createadynamicstatementinaprocedure.htm
This would be the alter table replacement, though I have tested this.
DECLARE l_sql VARCHAR(4000);
SET l_sql=CONCAT_ws(' ',
'ALTER table ',_TABLENAME,' drop column ',_FIELDNAME);
SET #sql=l_sql;
PREPARE s1 FROM #sql;
EXECUTE s1;
DEALLOCATE PREPARE s1;

Related

error 1178: syntax error in a stored procedure in mariadb columnstore

I try to produce a stored procedure that allows me to update many tables in my database but when I try to execute it with a columnstore engine, i get an error of procedure syntax not supported. I have looked for it in the web but do not manage to find where is the issue. If you have an idea, I let you the procedure here.
DELIMITER $$
CREATE PROCEDURE update_sp_aggregated()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE tableName varchar(255) DEFAULT "";
DECLARE cursor_update
CURSOR FOR
SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_name like 'sp_aggr%' ;
OPEN cursor_update;
updateAggregated: LOOP
FETCH cursor_update into tableName;
IF finished = 1 THEN
LEAVE updateAggregated;
END IF;
SET #sql = CONCAT('ALTER TABLE ', tableName, ' ADD COLUMN col2 varchar(5)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = CONCAT('UPDATE ', tableName, ' SET col2= LEFT(col1, 1)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP updateAggregated;
CLOSE cursor_update;
END $$
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET finished = 1;
DELIMITER ;
CALL update_sp_aggregated();
Finally found, so as tell in my comment, the issue was the update command was not allowed.
to solve it, you need to change the variable infinidb_vtable_mode by setting it to 0.
All is described here
and here

Execute SQL Stored procedure using Object_ID

Is there any way to accomplish this? For example, let's say the object_id for stored procedure X is 1234. I'm trying to do something like
EXEC ('EXEC Object_Name(1234)')
and it would run stored procedure X. Is there a way to accomplish this?
Thanks.
I guess you work with Oracle db.
To run procedure with known object_id you can use dictionary view all_objects and construct a call.
Here is an example:
declare
iObjectId number := 3927531;
sProcedureName varchar2(128);
sProcedureOwner varchar2(128);
begin
-- get the procedure name
for c in (
select object_name procedure_name,
owner procedure_owner
from all_objects
where object_type = 'PROCEDURE'
and object_id = iObjectId
) loop
sProcedureName := c.procedure_name;
sProcedureOwner := c.procedure_owner;
end loop;
if sProcedureName is not null then
execute immediate 'begin '||sProcedureOwner||'.'||sProcedureName||'; end;';
dbms_output.put_line('Procedure '||sProcedureName||' was executed successfully.');
else
dbms_output.put_line('Procedure was not found for object_id = '||iObjectId||'.');
end if;
end;
Keep in mind that procedure can have required parameters. In this case you can use the dictionary view all_arguments.
Hope that helps.

Oracle procedure/function to create a trigger in table

I'm trying to create a procedure that given a table name, it will create a sequence and auto incrementing trigger, all using variables based on the table name.
Code :
CREATE OR REPLACE procedure CREATE_SEQUENTIAL_TR(table_name VARCHAR)
is -- Tried using declare but it wouldn't accept
coluna_cod varchar(100 char);
begin
--Finding the cod column name for this table first
--They start with "PK_CD"
select
COLUMN_NAME
into
coluna_cod
from
ALL_TAB_COLUMNS
where
TABLE_NAME=table_name
and COLUMN_NAME like "PK_CD%";
--Creating the sequence obj
drop sequence "cod" || table_name;
create sequence "cod" || table_name;
--Now creating the trigger
create or replace trigger "cod" || table_name || "tr"
before
UPDATE or INSERT on table_name
for each row
declare
cod number := coluna_cod;
tr_name varchar(100 char) := "cod" || table_name
begin
if UPDATING then
if :new.cod != :old.cod then
:new.cod := :old.cod;
end if;
else -- inserting
:new.cod := tr_name.nextval();
end if;
end;
end;
The complexity of this ended up quite out of the scope of my knowledge.
At the moment it is giving an error on drop sequence "cod" || table_name (Unexpected DROP symbol found) but I'm sure I have made other errors.
Can someone help me figure this logic out?
You can't put DDL statements (like drop or create or alter) directly inside a PL/SQL block. If you want to do DDL inside PL/SQL, you can do an execute immediate:
declare
begin
drop sequence X; -- error
execute immediate 'drop sequence X'; -- works fine
end;
/

Alter each column named 'xxx'

I'm trying to create a PostgreSQL stored procedure that must set default value 'now()' to each columns named 'CreationDate' in every tables.
CREATE OR REPLACE FUNCTION set_creation_date() RETURNS
void AS $$
DECLARE
t pg_tables%ROWTYPE;
BEGIN
FOR t IN SELECT "tablename" FROM pg_tables WHERE "schemaname" = 'public' LOOP
IF EXISTS (select * from information_schema.columns where table_name = t."tablename"
and column_name = 'CreationDate') THEN
EXECUTE FORMAT('ALTER TABLE %I ALTER COLUMN "CreationDate" SET DEFAULT now()', t."tablename");
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
But no columns are affected. What's wrong?
It looks like it's trying to alter t."tablename" every time. Try the following instead:
EXECUTE FORMAT('ALTER TABLE %I ALTER COLUMN "CreationDate" SET DEFAULT now()', t."tablename");
I don't have a PostgreSQL server available to test, so please let me know if the syntax isn't quite right.
I finally resolved. The error was in pg_tables%ROWTYPE: using debugger i realized that the field 'tablename' doesn't exist, so i declared 't' as text.
I created a function with parameters, where you have to pass schema name and column name. I ll post it here for anyone who ll need it
DROP FUNCTION IF EXISTS set_creation_date(character varying, character varying);
CREATE OR REPLACE FUNCTION set_creation_date(_schema_name character varying, _column_date character varying)
RETURNS void AS
$BODY$
DECLARE
t TEXT;
BEGIN
FOR t IN SELECT "tablename" FROM pg_tables WHERE "schemaname" = _schema_name LOOP
IF EXISTS (select * from information_schema.columns where table_name = t and column_name = _column_date) THEN
EXECUTE FORMAT('ALTER TABLE %I ALTER COLUMN %I SET DEFAULT now()', t, _column_date);
END IF;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;

Netteza SQL ALTER TABLE in stored procedure alternative?

I want to alter a table within a For loop in Netteza SQL. I know that Netteza does not allow alter table in a stored procedure. As quoted:
"These SQL commands are also prohibited within the body of a Netezza stored procedure."
Are there any alternatives for doing so? I am a beginner in Netteza. I also don't know if my loop format is correct?
CREATE OR REPLACE PROCEDURE "SP_Automate_Table"()
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
vSQL1 varchar(30000) ;
BEGIN
FOR i in 2011..2014
LOOP
For j in 1..12
Loop
call "SP_Count"(i, j);
vSQL1:='alter table X add columnX INT';
....
...
..
EXECUTE immediate vSQL1;
END LOOP;
END LOOP;
END;
END_PROC;
Starting with v7.1 you can declare an AUTOCOMMIT ON block in a stored procedure, and in this block you can call statements that would otherwise be prohibited within a stored procedure.
CREATE OR REPLACE PROCEDURE ADMIN.SP_ALTER_LOOP(INTEGER, INTEGER)
RETURNS INTEGER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
pStartVal ALIAS FOR $1;
pCount ALIAS FOR $2;
vSQL varchar(30000);
BEGIN
BEGIN AUTOCOMMIT ON
for i in 1 .. pCount LOOP
vSQL := 'ALTER TABLE CLAIM_' || pStartVal + i-1 || ' ADD COLUMN (COL2 BIGINT);';
EXECUTE IMMEDIATE vSQL;
END LOOP;
END;
END;
END_PROC;
Prior to v7.1, I don't know of a way you can alter a table structure from with a stored procedure.
Note that in the general case of ALTER TABLE (whether scripted like this or manual), be sure to perform a groom of each altered table after the ALTER operation.
GROOM TABLE tablename VERSIONS;
Your loop statement is syntactically correct, but there is no way to issue alter statements from within nzplsql.
I would suggest doing a bash script as an alternative, repeatedly calling nzsql.
for i in $(seq 2011 2014); do
for j in $(seq 1 12); do
nzsql -c "call \"SP_Count\"($i, $j);"
nzsql -c "alter table X add columnX INT;"
done
done
I can't really imagine a use case where you'd want to dynamically add columns by calling a stored procedure from within a database that couldn't also be covered by doing it outside the database.