How to remove quotes in sybase ASE - stored-procedures

I have a string:
"16680,16678,16677,16676,16675,16672"
Which I got from the Stored procedure passed parameter while calling it. I want to insert these records in where in like
Where in (16680,16678,16677,16676,16675,16672).
How can I make this in Sybase ASE stored procedure?

You can use the str_replace() function to replace the double quotes with NULL, eg:
declare #strings varchar(15)
select #strings = '"1,2,3,4,5"'
select #strings, str_replace(#strings,'"',NULL)
go
--------------- ---------------
"1,2,3,4,5" 1,2,3,4,5
Feeding the new string into a query requires a bit more work though.
Trying to feed directly into a query generates an error, eg:
declare #strings varchar(15)
select #strings = '"1,2,3,4,5"'
select id from sysobjects where id in ( str_replace(#strings,'"',NULL) )
go
Msg 257, Level 16, State 1:
Server 'ASE400', Line 7:
Implicit conversion from datatype 'VARCHAR' to 'INT' is not allowed. Use the CONVERT function to run this query.
To get around this issue we can dynamically build the query and then run it via an execute() call, eg:
declare #strings varchar(15),
#query varchar(100)
select #strings = '"1,2,3,4,5"'
select #query = 'select id from sysobjects where id in (' || str_replace(#strings,'"',NULL) || ')'
print #query
execute (#query)
go
select id from sysobjects where id in (1,2,3,4,5)
id
-----------
1
2
3
4
5
Another solution that does away with the #query variable:
declare #strings varchar(15)
select #strings = '"1,2,3,4,5"'
select #strings = str_replace(#strings,'"',NULL)
execute( 'select id from sysobjects where id in (' || #strings || ')' )
go
id
-----------
1
2
3
4
5
NOTE: all code was run in an ASE 16.0 SP04 GA instance.

Related

Solve the syntax error with Redshift operator does not exist and add explicit casts

I am a newbie in the area of redshift data modeling and got myself into trouble with an error.ERROR:
--Final version
syntax error ERROR: operator does not exist: text | record Hint: No
operator matches the given name and argument type(s). You may need to
add explicit type casts. Where: SQL statement "SELECT 'create temp
table ' || $1 || ' as select * from' | $2 |" PL/pgSQL function "egen"
line 36 at execute statement [ErrorId:
1-61dc32bf-0a451f5e2c2639235abb8876]
I am trying to do a simple transformation that gets returned in output when the procedure is called. (As of now I got to find from the documentation we have to use either temp table or cursors to achieve this)
Pseudocode:
I am trying to restrict data to its latest one in (2019) Get the
list of managers create columns if a person is a manager or not from the list.
Return it as a result
Data looks as follows Employee Data
My Select query works fine out of the procedure, please find my complete code below.
CREATE OR REPLACE PROCEDURE EGEN(tmp_name INOUT varchar(256) )
AS $$
DECLARE
--As i have less data managed to create it as an array or please use temp or table and join it with the actual query to perform transformation
MGR_RECORD RECORD;
DATAS RECORD;
item_cnt int := 0;
V_DATE_YEAR int := 0;
BEGIN
--EXECUTE (select cast(extract(year from current_date) as integer)-3) INTO V_DATE_YEAR;
--Manager Records are stored here below
SELECT DISTINCT managerid from "dev"."public"."emp_salary" INTO MGR_RECORD;
SELECT employeeid,
managerid,
promotion,
q_bonus,
d_salary,
case when contractor = 'x'
then 'TemporaryEmployee'
else 'PermanentEmployee'
END as EmployeeType,
-- IFstatement not supported under select query
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
FROM "dev"."public"."emp_salary" where cast(extract(year from promotion) as int ) >= 2019 into DATAS;
--COMMIT;
tmp_name := 'ManagerUpdatedTable';
EXECUTE 'drop table if exists ' || tmp_name;
EXECUTE 'create temp table ' || 'ManagerUpdatedTable' || ' as select * from' |DATAS| ;
END;
$$ LANGUAGE plpgsql;
-- Call tests CALL EGEN('myresult'); SELECT * from myresult;
Also, additional query (Can we replace )
case when employeeid in (select distinct managerid FROM "dev"."public"."emp_salary" )
then 'Manager'
else 'Ordinary FTE'
END as FTETYPE
this transform in query to IF , if possible please provide details.
Thanks and Regards,
Gabby

Create dynamic SQL based on column names passed through a string

I need to find out rows that are present in table A and missing from table B (using LEFT JOIN) wherein table A and table B are two tables with same structure but within different schema.
But the query has to be constructed using Dynamic SQL and the columns that need to be used for performing JOIN are stored in a string. How to extract the column names from string and use them to dynamically construct below query :
Database is Azure SQL Server
eg :
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
Query to be constructed based on columns defined in ColNames :-
SELECT *
FROM Table A
Left Join
Table B
ON A.col1 = B.col1
AND A.col2 = B.col2
AND B.col1 IS NULL AND B.col2 IS NULL
If the number of columns in #ColNames is more then the SELECT statement needs to cater for all the column.
Without knowing the full context, try this:
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
DECLARE #JoinContion NVARCHAR(MAX) = ''
DECLARE #WhereCondition NVARCHAR(MAX) = ''
SELECT #JoinContion += CONCAT('[a].', QUOTENAME(Value), ' = ', '[b].', QUOTENAME(Value), (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
,#WhereCondition += CONCAT('[a].', QUOTENAME(Value), ' IS NULL', (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
FROM STRING_SPLIT(#ColNames,N',')
SELECT #JoinContion, #WhereCondition
String_Split: To split the input string into columns
Lead: to determine if we need the AND keyword when it's not the last row.
Be aware the NOT EXISTS is probably a better solution then LEFT JOIN

Conversion failed when converting the varchar value '1,2' to data type int

When I pass more than one id in sql server stored procedure it throws error like this==> Conversion failed when converting the varchar value '1,2' to data type int.
and this is the sql query
===>SELECT * FROM SomeTAble WHERE colName in(#Ids)
If your stored procedure parameter expecting varchar(n), please have a look at accepted answer from T-SQL split string to split the value from a varchar.
Then you can apply the function in your stored procedure, you can simply change the query to something like this:
alter procedure your_stored_procedure
#ids varchar(50)
as
begin
select *
from some_table
where colName in (splitstring(#ids))
end
go
However, if your stored procedure accepting int as parameter, please change it to varchar or any data type. Your stored procedure won't work because int will only accept single integer value.
You have to split string into rows first.
for do that you can use my sql Splitext function
Here is Installing Script
DROP FUNCTION IF EXISTS [dbo].[SplitText]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SplitText]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
BEGIN
execute dbo.sp_executesql #statement = N'CREATE FUNCTION [dbo].[SplitText]
( #TextForSplit varchar(1000)
, #SplitWith varchar(5) = '',''
)
RETURNS #DataSource TABLE
(
ID TINYINT identity,
[Value] VARCHAR(500) NOT NULL
)
AS
BEGIN
DECLARE #XML xml = N''<r><![CDATA['' + REPLACE(#TextForSplit, #SplitWith, '']]></r><r><![CDATA['') + '']]></r>''
INSERT INTO #DataSource ([Value])
SELECT RTRIM(LTRIM(T.c.value(''.'', ''NVARCHAR(128)'')))
FROM #xml.nodes(''//r'') T(c)
DELETE #DataSource WHERE [VALUE] = ''''
RETURN
END
END
GO
And this is how to use it.
SELECT * FROM SomeTAble WHERE colName in( select value from Splittext('1,2,3,4,5' , ','))

Tokene unknown creating a stored procedure with dynamic table name

I try to check existence of a record before inserting into table.
SET TERM ^ ;
CREATE PROCEDURE add_videorecord(tab_name varchar(31), col_name varchar(31),
col_value varchar(100))
RETURNS (status int)
AS
BEGIN
status=1;
if (not exists(
select * from :tab_name where :col_name = :col_value))
then
execute statement 'insert into "'||:tab_name||'" ("'||:col_name||'") values("'||:col_value||'")';
else
status=0;
END^
SET TERM ; ^
And get FlameRobin error:
Message: isc_dsql_prepare failed
SQL Message : -104
Invalid token
Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 10, column 15
:
Why it's unknown token? I try to use the input parameter.
You can't directly parametrize an object name (like a table name, column name, etc) like you do in your select. Parameters can only be used for values.
If you want to parametrize an object name, you need to concatenate it into a query string, like you already do for your insert statement. You just need to watch out for SQL injection (eg by checking the name against a known set of accepted object names).
As an example (without checking for valid table and column name!):
CREATE PROCEDURE ADD_RECORD (
TAB_NAME VARCHAR(31),
COL_NAME VARCHAR(31),
COL_VALUE VARCHAR(100) )
RETURNS (
STATUS INTEGER )
AS
DECLARE temp INTEGER;
BEGIN
status=1;
execute statement
('select 1 from "' || tab_name || '" where "' || col_name || '" = ?') (:col_value)
into :temp;
if (temp is null)
then
execute statement
('insert into "'|| tab_name||'" ("' || col_name|| '") values(?)') (:col_value);
else
status=0;
END
Using a single (dynamically created) MERGE statement, you might be able to simplify this further.

Pass comma separated number to IN clause in Stored Procedure

I have a stored procedure which takes a varchar parameter called P_LOCATIONS in Oracle. This locations parameter has location id's that are comma separated. In database locationId is a number.
Following sql query throws an Invalid number when there are more than one locations. I understand that because of comma its not able to convert a varchar into a number. How can I achieve this?
create or replace PROCEDURE GET_RAW_DATA
( P_LOCATIONS IN VARCHAR2,
Results OUT SYS_REFCURSOR
)AS
BEGIN
select * from tableName where LOCATION_ID IN ( P_LOCATIONS);
END GET_RAW_DATA;
The end result of what you are doing is this:
select * from tableName where LOCATION_ID IN ('1,2,3');
And what you need is this:
select * from tableName where LOCATION_ID IN (1,2,3);
So you can use this:
select * from tableName where LOCATION_ID in (
select regexp_substr(P_LOCATIONS,'[^,]+{1}',1,level)
from dual connect by level <= length(regexp_replace(P_LOCATIONS,'[^,]*')) + 1
);

Resources