I am trying to create a UDTF in Snowflake but I get an error on RETURNS TABLE even though it matches the syntax - function

CREATE OR REPLACE FUNCTION DQ_IS_NULL ("SCHEMA_NAME" VARCHAR(500), "TABLE_NAME" VARCHAR(500), "COLUMN_NAME" VARCHAR(500))
RETURNS TABLE (TABLE_NME VARCHAR(500), COLUMN_NME VARCHAR(500), ISSUE_CODE VARCHAR(100), PARAMETERS VARCHAR(500), VALUE VARCHAR (500), ROW_HASH NUMBER(19,0), EXECUTION_TS TIMESTAMP)
LANGUAGE SQL
AS
'
SELECT
TABLE_NAME,
COLUMN_NAME,
CASE
WHEN V IS NOT NULL
THEN ''NULLed''
END AS ISSUE_CODE,
CASE
WHEN COLUMN_NAME IS NOT NULL
THEN ''NULLS not permitted''
END AS PARAMETERS,
HASH(*) AS ROW_HASH,
CURRENT_TIME() AS EXECUTION_TS
FROM CONCAT(SCHEMA_NAME ,''.'',TABLE_NAME)
WHERE COLUMN_NAME IS NULL
The function is intended to return all rows in a given table that are null

The problem is that you're using ' to denote the start of the function definition, but there is a ' within the body as well. You can use $$ to work around the issue:
CREATE OR REPLACE TEMP FUNCTION DQ_IS_NULL ("SCHEMA_NAME" VARCHAR(500), "TABLE_NAME" VARCHAR(500), "COLUMN_NAME" VARCHAR(500))
RETURNS TABLE (TABLE_NME VARCHAR(500), COLUMN_NME VARCHAR(500), ISSUE_CODE VARCHAR(100), PARAMETERS VARCHAR(500), VALUE VARCHAR (500), ROW_HASH NUMBER(19,0), EXECUTION_TS TIMESTAMP)
LANGUAGE SQL
AS
$$
SELECT
TABLE_NAME,
COLUMN_NAME,
CASE
WHEN V IS NOT NULL
THEN 'NULLed'
END AS ISSUE_CODE,
CASE
WHEN COLUMN_NAME IS NOT NULL
THEN 'NULLS not permitted'
END AS PARAMETERS,
HASH(*) AS ROW_HASH,
CURRENT_TIME() AS EXECUTION_TS
FROM CONCAT(SCHEMA_NAME ,''.'',TABLE_NAME)
WHERE COLUMN_NAME IS NULL
$$;
Note that there's another issue still, however; you need to use a real table name in the UDTF body, as opposed to CONCAT(SCHEMA_NAME ,''.'',TABLE_NAME).

Related

Set default variables within MySQL functions if values are not correct

when selecting a customers name from a table the database should call a function that formats the name to
lastname, firstname
The function I created is
CREATE DEFINER=`root`#`localhost` FUNCTION `FORMAT_NAME`(firstname VARCHAR(25), lastname VARCHAR(25)) RETURNS varchar(50) CHARSET utf8
RETURN CONCAT(lastname, ', ', firstname)
Within my SELECT I can now write
SELECT FORMAT_NAME(customer.firstname, customer.lastname) as Name
and this returns me
Doe, John
Normally I would solve this by code but I have to use a FUNCTION and have to set up default variables.
How can I define default variables here if a value is empty or null or just not correct?
You just need to use the COALESCE function :
CREATE DEFINER=`root`#`localhost` FUNCTION `FORMAT_NAME`(firstname VARCHAR(25),
lastname VARCHAR(25)) RETURNS varchar(50) CHARSET utf8
RETURN CONCAT(COALESCE(lastname, 'myDefaulValueName'), ', ', COALESCE(firstname, 'myDefaultValueFName'))

SSRS - Only allow data to be entered into one parameter

I have a report with 3 parameters. Problem is, I only want data to be entered into one of those parameters. If data is present in more than one parameters, I want the end user to get a warning message. The reason behind this is that, depending on what parameter has data, it creates a separate temp table to compile result data. If more than one is entered, it end up locking the SQL server.
I'm on SQL 2008. How can I accomplish this?
Here are my parameters in ssrs:
...and here is my stored proc. If one of the parameters contains a value, a null value is passed to the other two parameters
CREATE PROC [dbo].[uspS_SerialNumberLookupReport] #_SalesOrder AS VARCHAR(10) ='', #_AQNum AS VARCHAR(10) ='', #_Serial AS VARCHAR(10) =''
AS
IF OBJECT_ID('tempdb..#SerialNumberLookupReport') IS NOT NULL
DROP TABLE #SerialNumberLookupReport
CREATE TABLE #SerialNumberLookupReport
(Company varchar(1),
Serial varchar(15),
StockCode varchar(30),
Description varchar(50),
SalesOrder int,
OrderDate datetime,
ReqShipDate datetime,
CustomerPoNumber varchar(10),
CustomerName varchar(50),
ShippingInstrs varchar(50),
ShippingCarrier varchar(50),
ShippingLink varchar(1000))
INSERT INTO #SerialNumberLookupReport
EXEC uspS_SerialNumberLookupX #SalesOrder=#_SalesOrder, #AQNum=#_AQNum, #Serial=#_Serial
INSERT INTO #SerialNumberLookupReport
EXEC uspS_SerialNumberLookupE #SalesOrder=#_SalesOrder, #AQNum=#_AQNum, #Serial=#_Serial
SELECT DISTINCT
Company
,Serial
,StockCode
,Description
,SalesOrder
,OrderDate
,ReqShipDate
,CustomerPoNumber
,CustomerName
,ShippingInstrs
,ShippingCarrier
,ShippingLink
FROM #SerialNumberLookupReport
you could use 2 parameters instead, like
to answer comment:
you could use your existing parameters as variables like:
create proc some_stored_proc
(#id_type varchar(30) , #value varchar(50))
as
declare
#SalesOrder varchar(50) null,
#Serial varchar(50) null,
#AQ varchar(50) null
if #id_type = 'Sales Order#'
set #SalesOrder = #value
else
if #id_type = 'Serial#'
set #Serial = #value
else
if #id_type = 'AQ#'
set #AQ = #value

syntax error : 1064 , when creating a stored procedure

CREATE table parent_user
( userid int auto_increment PRIMARY KEY,
Username varchar(100) NOT NULL,
Password varchar(200) NOT NULL,
Email varchar(200) NOT NULL
);
EDIT : OK so I made some changes:
CREATE PROCEDURE `parent_reg` (
pUserName varchar(100)
pPassword varchar(200)
pEmail varchar(200)
)
as
Begin
Declare Count int
Declare ReturnCode int
Select Count = Count(Username)
from parent_user where Username = #Username
If Count > 0
Begin
Set ReturnCode = -1
End
Else
Begin
Set ReturnCode = 1
insert into parent_user values
(pUserName, pPassword, pEmail)
End
Select pReturnCode as ReturnValue
End
But I still got the same error-
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'pPassword varchar(200) pEmail varchar(200) ) ....'
The syntax error is at 'pPassword varchar(200)'
The code in the question is invalid syntax for MySQL Stored Procedure. It looks more like Microsoft SQL Server (Transact SQL) syntax.
Some observations:
MySQL procedure variables cannot start with # because that character is reserved for user-defined variables.
MySQL doesn't use a NVARCHAR type. The setting of the character_set_client variable in the session (at the time the procedure is created) is what controls the characterset of the procedure variables.
The line select * from parent_user, before the CREATE PROCEDURE looks entirely out of place.
Missing semicolons (statement terminators).
The INSERT is for a table with four columns; there are only three values and no column list.
If the goal is to create a stored procedure in MySQL, we'd need syntax closer to this:
DELIMITER $$
CREATE PROCEDURE parent_reg(p_username VARCHAR(100),
p_password VARCHAR(200), p_email VARCHAR(200)
)
BEGIN
DECLARE mycount INT;
DECLARE myreturncode INT;
SELECT COUNT(pu.username)
INTO mycount
FROM `parent_user` pu
WHERE pu.username = p_username;
IF (mycount > 0 ) THEN
SET myreturncode = -1;
ELSE
SET myreturncode = 1;
INSERT INTO `parent_user` (`username`, `password`, `email`)
VALUES (p_username, p_password, p_email);
END IF;
SELECT myreturncode AS `ReturnValue`;
END$$
DELIMITER ;
Maybe it's your database's collation. When installing SQL Server and choose your default collation, there's a "case sensitivity" checkbox. Certain collations are case sensitive and will affect your queries (and stored procedures).
A lot of vendors don't test their products on servers with case sensitive collations, which leads to runtime errors.
So just try to choose between "Username" and "UserName"

How do I modify a MySQL column to allow NULL without specifying its data type?

I have a table in mysql and I want to alter a table to allow a column to be null.
When I do describe on my mysql table, I see these things in mysql workbench:
Field Type Null Key Default Extra
I want to set Null field as YES for a particular column. Here is how I am trying which works fine but do I need to provide its data type while setting DEFAULT to NULL?
ALTER TABLE abc.xyz CHANGE hello hello int(10) unsigned DEFAULT NULL;
ALTER TABLE abc.xyz CHANGE world world int(10) unsigned DEFAULT NULL;
Is there any other way by which I can just pick column name and set default to NULL instead of using its data type as well? I don't want to provide int(10) while setting its default to NULL.
You're kind of on the wrong track. Changing the default to NULL does not "allow" the column to be null: what you need to do is drop the "NOT NULL" constraint on the column.
But to redefine the nullability of a column through script, you will have to continue to reference the datatype. You'll have to enter something like
ALTER TABLE MyTable MODIFY COLUMN this_column Int NULL;
Not sure if this applies if you're looking for a straight DDL statement, but in MySQL Workbench you can right-click on a table name, select "Alter Table..." and it will pull up a table definition GUI. From there, you can select null/not null (among all the other options) without explicitly listing the column's datatype. Just a "for what it's worth"...
This can be done with the help of dynamic statements.
Usage:
CALL sp_make_nullable('schema_name', 'table_name', 'column_name', TRUE);
Implementation:
DELIMITER $$
create procedure eval(IN var_dynamic_statement text)
BEGIN
SET #dynamic_statement := var_dynamic_statement;
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END;
DELIMITER ;
DELIMITER $$
create procedure sp_make_nullable(IN var_schemaname varchar(64), IN var_tablename varchar(64),
IN var_columnname VARCHAR(64), IN var_nullable BOOLEAN)
BEGIN
DECLARE var_column_type LONGTEXT DEFAULT (SELECT COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = var_schemaname
AND TABLE_NAME = var_tablename
AND COLUMN_NAME = var_columnname);
DECLARE var_nullable_prefix VARCHAR(64) DEFAULT '';
IF NOT var_nullable THEN
SET var_nullable_prefix := 'NOT';
end if;
CALL eval(CONCAT('
ALTER TABLE ', var_schemaname, '.', var_tablename,
' MODIFY ', var_columnname, ' ', var_nullable_prefix, ' NULL
'));
end$$
DELIMITER ;

SELECT inside stored proc doesn't work correctly whereas outside it does

i have a simple database as follows in mysql:
DROP TABLE IF EXISTS MEDIAVEND.ITEMDETAILS;
CREATE TABLE IF NOT EXISTS MEDIAVEND.ITEMDETAILS (
ItemID BIGINT UNSIGNED NOT NULL,
ITEMTYPE ENUM('MUSIC', 'MOVIE', 'GAME') NOT NULL,
ITEMMEDIATYPE ENUM('CD', 'DVD', 'BLURAY') NOT NULL,
ITEMNAME CHAR(100) NOT NULL,
ITEMDESCRIPTION CHAR(200) NOT NULL,
ITEMCOUNT BIGINT NOT NULL,
MACHINEID BIGINT NOT NULL,
PRIMARY KEY (ITEMID)
);
INSERT INTO MEDIAVEND.ITEMDETAILS VALUES
(1,'MUSIC','CD','ALBUM 1','SOME DESCRIPTION OF 1',100,1),
(2,'MUSIC','CD','ALBUM 2','SOME DESCRIPTION OF 2',20,1),
(3,'MOVIE','DVD','MOVIE 1','SOME DESCRIPTION OF 1',30,1),
(4,'MOVIE','BLURAY','MOVIE 2','SOME DESCRIPTION OF 2',40,1),
(5,'GAME','DVD','GAME 1','SOME DESCRIPTION OF 1',50,1),
(6,'GAME','BLURAY','GAME 2','SOME DESCRIPTION OF 2',60,1);
and a stored proc as :
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `info_ItemType`(in itemType char(10))
BEGIN
SELECT * FROM MEDIAVEND.ITEMDETAILS WHERE ITEMTYPE= itemType;
END
so when i call following i see different results.
select * from mediavend.itemdetails where itemType='MUSIC';
-- 2 rows returned
call mediavend.info_ItemType('MUSIC');
-- 6 rows returned
i am really baffled, pardon me if it is a silly mistake, but i have gone through lots of questions and don't see any relevant to this.
Rename your input parameter since it has the same name as the column.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `info_ItemType`(in itemType_Param char(10))
BEGIN
SELECT * FROM MEDIAVEND.ITEMDETAILS
WHERE ITEMTYPE = itemType_Param;
END
$$
MySQL is not case sensitive, so when you say where ITEMTYPE = itemType, you're looking for where the column is equal to itself, hence all rows are returned.
You need to use a unique parameter name.