Having trouble with SQL stored function syntax - sql

I have this problem and I don't know what it means. As far as I understand you make a procedure inside a database so how do I write a procedure that specifies the database if it is different than the database I created the procedure in? I have asked and not received any clarification from my instructor about this. Here is the problem I am trying to solve:
Using SQL again, write a procedure that allows a user to specify a database, table, column in the table, and the new name of the index. This allows a user to add indexes without remembering the SQL syntax.
This is what I have so far come up with, but it doesn't seem to work. Or at least maybe I am writing the wrong thing in my query
CREATE DEFINER=`root`#`localhost` PROCEDURE `addindex`(
IN `db_name` VARCHAR(255),
IN `tbl_name` VARCHAR(255),
IN `col_name` VARCHAR(255),
IN `idx_name` VARCHAR(255)
)
BEGIN
CREATE INDEX idx_name ON db_name.tbl_name(col_name);
END
what I put in the query
addindex(nation, countries, AREA, index_area);
nation, countries, and area are the database, table, and column of a database I am using for testing this.

Tables, Database and Column names are identifiers and can't be variables.
What you can do in the body is use execute immediate like:
EXECUTE IMMEDIATE CONCAT('CREATE INDEX ',
idxname, ' on ', dbname, '.', tblname,
'(', col_name, ')')
Note this hasn't done table quoting. QUOTE() could be used around each of these identifiers.
Also consider compound multi-column indexes are useful and that stored procedures can't be written with a variable number of arguments. Hence quote(col_name) when multiple columns are passed will make it look like a single column.

Related

If not exist clause SQL statement

so I found this sql query in a project I am succeeding. This is the first time I encountering this clause/statement. I understand that this is to look if the table exist before creating one and that Object_ID is the table name that is to be created.
My questions are:
Does sysobject mean the database?
What is the Object property?
I know that it is not the columns inside the table to be created.
The columns are : dtb_color_id and description.
can someone explain this to me. please?
IF NOT EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('DTB_COLOR') AND OBJECTPROPERTY(ID,'ISUserTable') = 1)
BEGIN
.......some query I understand
END
sysobjects, OBJECTPROPERTY and OBJECT_ID are used in Microsoft SQL Server. They are part of the SQL Server DMVs and system functions/procedures used to query and manipulate the metadata.
sys.sysobjects is simply the list of all objects (tables, views, SPs, functions, etc) on the server in the active database. Please note, that sys.sysobjects is deprecated and is only available for backward compatibility. Use sys.objects instead
https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/system-dynamic-management-views?view=sql-server-ver16
It has (as far as I know) no meaning in MySQL, unless somebody specifically created them.
You can also use INFORMATION_SCHEMA which is available in MySQL too (however slightly different in different RDBMS).
MSSQL INFORMATION_SCHEMA: https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/system-information-schema-views-transact-sql?view=sql-server-ver16
MySQL INFORMATION_SCHEMA: https://dev.mysql.com/doc/refman/8.0/en/information-schema.html
SQL Server has no CREATE TABLE IF NOT EXISTS construct, a variation of the mentioned condition is commonly used to imitate that.
This is a way in SQL Server to check if a table exists in the active database and to perform actions according to the result, like creating the table.
OBJECTPROPERTY simply checks (in this case) if the table is a user created one.
https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-ver16
I would remove the OBJECTPROPERTY condition in case the part you understand is a CREATE TABLE statement. You don't want to create a table which has a similar name to any system table/view, also you don't want to execute the CREATE TABLE if there is a VIEW with the same name (table creation will fail)
Yes sysobject means database.
The OBJECTPROPERTY() function returns information about schema-
scoped objects in the current database. Use this to check if an
object is a table, view, stored procedure, etc. You can also use
it to check if a table has a primary key, foreign key, foreign
key reference, etc.
For more details : https://learn.microsoft.com/en-us/sql/t-sql/functions/objectpropertyex-transact-sql?view=sql-server-ver16
In this scenario it is used to check whether it is user table or
not. The result of the ISUserTable property is 1 when it is user
table otherwise returns 0.
Here the following steps are followed:
First, it executes the select statement inside the IF Exists
If the select statement returns a value that condition is TRUE for IF Exists
It starts the code inside a begin statement
DTB_COLOR - May be a stored procedure

Hana: How to create a table type LIKE the type of another table?

I'm trying to create a table type which has a lot of fields, in SQLScript for a Hana machine.
I've tried some combinations of 'Like' and other keywords but it all comes out as a syntax error.
Furthermore, I could not find any hint of this in the SQLScript reference guide.
I've been creating tables LIKE [orignal table] with no data and inserting records into it - not practical :(
Thanks in advance.
Miguel
EDIT: to understand if the procedure 'get_object_definition' can be used with tables with case-sensitive names.
In this image we can see the procedure calls, with the error message; in the image after, the tables and table types in each of the schemas.
EDITED: I got it, have to call the procedure with ' " table_name " '
There is no specific command to create a type based on an existing table or another type.
What you can do is to get the definition of the table via
call get_object_definition ('<schema name>', '<table name>');
and edit the object creation statement to a CREATE TYPE statement. This is basically just changing the starting part of the statement and cutting away some parts at the end.

TSQL substitution of key words and code blocks

I have blocks of TSQL that I want to create a MACRO for and then reuse in my SQL file. I want this to be a 'compile' time thing only.
Eg:
?set? COMMON = "Field1 int, Field2 char(1),";
?set? MAKEONE = "create table";
MAKEONE XXX (
COMMON
Field3 int
);
Please dont ask why I would want to ... :)
... it is for SQL Server.
Ok, what about conditional execution of SQL:
?set? ISYES = true;
?if? ISYES
create table AAA (...)
?else?
create table BBB (...)
What you are asking makes little sense in SQL terms
Based on your examples:
A CREATE TABLE is exactly that: a CREATE TABLE. Why Macro it? You aren't going to substitute "CREATE PROCEDURE".
Having "common" fields would indicate poor design
You also have to consider:
constraints, keys and indexes
permissions of using dynamic SQL
the cost of developing a "framework" to do what SQL already does
permissions of your objects
Now, what is the business problem you are trying to solve?
Instead of asking about your chosen solution...
Edit: question updated as I typed above:
IF (a condition)
EXEC ('CREATE TABLE ...')
ELSE IF (a condition)
EXEC ('CREATE TABLE ...')
...
Note that much of DDL in SQL must be in it's own batch or the first statement in a batch. Hence use of dynamic SQL again

MySQL Stored Procedure dynamic change name of table

I wanna change dynamicaly name of table in sql query. For example I have next stored procedure:
CREATE PROCEDURE NewProc(IN tableName varchar(64),IN message text)
BEGIN
INSERT INTO tableName VALUES (message);
END;
I need to change tableName in runtime, Can I to do it or not?
Thanks.
You must use dynamic SQL to prepare and execute an SQL string, to achieve what you describe.
Dynamic table names (or column names, or SQL keywords, etc.) must be interpolated into the SQL string before prepare. You can't use query parameters for these dynamic elements.
Be careful to avoid SQL injection vulnerabilities when you interpolate the table name into your SQL query. For example, you should check that the table name exists by looking it up in the information schema.
I agree with the comment from #OMG Ponies -- it's a code smell that you have multiple tables with identical structure such that you want to do the exact same insert to the exact same column. Code smells aren't a guarantee that you've got a bad design, but it's worth considering.

PL/SQL embedded insert into table that may not exist

I much prefer using this 'embedded' style inserts in a pl/sql block (opposed to the execute immediate style dynamic sql - where you have to delimit quotes etc).
-- a contrived example
PROCEDURE CreateReport( customer IN VARCHAR2, reportdate IN DATE )
BEGIN
-- drop table, create table with explicit column list
CreateReportTableForCustomer;
INSERT INTO TEMP_TABLE
VALUES ( customer, reportdate );
END;
/
The problem here is that oracle checks if 'temp_table' exists and that it has the correct number of colunms and throws a compile error if it doesn't exist.
So I was wondering if theres any way round that?! Essentially I want to use a placeholder for the table name to trick oracle into not checking if the table exists.
EDIT:
I should have mentioned that a user is able to execute any 'report' (as above). A mechanism that will execute an arbitrary query but always write to the temp_table ( in the user's schema). Thus each time the report proc is run it drops the temp_table and recreates it with, most probably, a different column list.
You could use a dynamic SQL statement to insert into the maybe-existent temp_table, and then catch and handle the exception that occurs when the table doesn't exist.
Example:
execute immediate 'INSERT INTO '||TEMP_TABLE_NAME||' VALUES ( :customer, :reportdate )' using customer, reportdate;
Note that having the table name vary in a dynamic SQL statement is not very good, so if you ensure the table names stay the same, that would be best.
Maybe you should be using a global temporary table (GTT). These are permanent table structures that hold temporary data for an Oracle session. Many different sessions can insert data into the same GTT, and each will only be able to see their own data. The data is automatically deleted either on COMMIT or when the session ends, according to the GTT's definition.
You create the GTT (once only) like this:
create globabal temporary table my_gtt
(customer number, report_date date)
on commit delete/preserve* rows;
* delete as applicable
Then your programs can just use it like any other table - the only difference being it always begins empty for your session.
Using GTTs are much preferable to dropping/recreating tables on the fly - if your application needs a different structure for each report, I strongly suggest you work out all the different structures that each report needs, and create separate GTTs as needed by each, instead of creating ordinary tables at runtime.
That said, if this is just not feasible (and I've seen good examples when it's not, e.g. in a system that supports a wide range of ad-hoc requests from users), you'll have to go with the EXECUTE IMMEDIATE approach.