Convert NULL Text to Null Value - sql-server-2008

I have a situation where I may need to pass a variable that could possibly hold a NULL value to a function, but through sp_executesql, so I will need to convert it to string value via string concatenation.
For Example:
declare #var1 varchar(10) = 'value'
declare #var2 varchar(10) = null
declare #sql nvarchar(2000)
.
.
set #sql = '
select dbo.fn_Scalar(''' + #var1 + ''', ''' + #var2 + ''' )
'
Function Definition:
Create Function [dbo].[fn_fn_Scalar]
(
#var1 varchar(10) ,
#var2 varchar(10) = null
) RETURNS float
AS BEGIN
Declare #ret float
Select #ret = sum(value)
from Table
where Field1 = #var1
and Field2 like isnull(#var2, '%')
return #ret
END
What would be the best approach to allow for fn_Scalar to be called via Dynamic and Static SQL statements and still allow for the second parameter to either be set to a value, NULL, or default.

You can pass parameters to sp_executesql function like so:
declare #var1 varchar(10) = 'value'
declare #var2 varchar(10) = null
Set #ParamDefinition = '#var1 varchar(10), #var2 varchar(10)'
Execute sp_Executesql 'select dbo.fn_Scalar(#var1,#var2)', #ParamDefinition, #var1, #var2

Related

Printing dynamic SQL with parameter values

I want to print the SQL query which is used in the below stored procedure with parameter values. Currently it is printing the SQL query without parameter
values substitution while executing the stored procedure. It is printing the the parameters as it is (for example AND TP.F_LANGUAGE = #LANGUAGE)
CREATE PROCEDURE [dbo].[SEARCH]
#LANGUAGE VARCHAR(2),
#SUBFORMAT NVARCHAR(2000),
#ICO NVARCHAR(4000),
AS
SET NOCOUNT ON
DECLARE #sqlQuery AS NVARCHAR(MAX)
DECLARE #pdfQuery AS NVARCHAR(MAX)
DECLARE #htmlQuery AS NVARCHAR(MAX)
DECLARE #param AS NVARCHAR(3000)
DECLARE #paramDefinition AS NVARCHAR(3000)
DECLARE #AllSubformats AS SubformatType
DECLARE #InputSubformats AS SubformatType
INSERT INTO #AllSubformats(Val)
SELECT S.Val
FROM (SELECT IsNull(TLK.f_value, '') As FValue
FROM T_LOOKUP TLK
WHERE TLK.f_parent = 'WEBVIEWER_INT_SUB') TLV
CROSS APPLY dbo.dfnSplit(TLV.FValue, ',') S;
IF (#SUBFORMAT <> '-1')
BEGIN
INSERT INTO #InputSubformats(Val)
SELECT S.Val
FROM dbo.dfnSplit(#SUBFORMAT, ',') S
END;
SET #pdfQuery = 'SELECT TOP 1001 TP.F_PRODUCT AS ID,
TP.F_PRODUCT_NAME AS NAME,
FROM PDF_DETAILS TP '
WHERE TP.F_PRODUCT<>'''''
SET #param = ' AND TP.F_AUTHORIZED IN(1,3) AND EXISTS (SELECT 1 FROM #AllSubformats ASF WHERE ASF.Val = TP.F_SUBFORMAT)'
IF NOT(#LANGUAGE IS NULL OR #LANGUAGE = '')
SET #param = #param + ' AND TP.F_LANGUAGE = #LANGUAGE '
IF NOT(#SUBFORMAT IS NULL OR #SUBFORMAT = '')
SET #param = #param + ' AND EXISTS (SELECT 1 FROM #InputSubformats ISF WHERE ISF.Val = TP.F_SUBFORMAT) '
IF NOT(#ICO IS NULL OR #ICO = '')
SET #param = #param + ' AND (TP.F_ICO_DATA LIKE #ICO) '
SET #ParamDefinition = ' #SUBFORMAT NVARCHAR(2000),
#LANGUAGE VARCHAR(2), #ICO NVARCHAR(4000),#AllSubformats SubformatType READONLY, #InputSubformats SubformatType READONLY '
SET #sqlQuery = #pdfQuery + #param
EXECUTE SP_EXECUTESQL #sqlQuery, #paramDefinition, #SUBFORMAT, #LANGUAGE, #ICO, #AllSubformats, #InputSubformats
Print #sqlQuery
Please help.I want to debug and execute the SQL QUERY.
You could PRINT the result of a REPLACE function. You would need to nest a REPLACE for every parameter in the string:
PRINT REPLACE(
REPLACE(#sqlQuery, '#Parameter1', #Parameter1)
, '#Parameter2', #Parameter2
);
Note this assumes all of your parameters are string types. If any of them are non-string, you will need to CAST them to strings inside the REPLACE.

Sorting integers in a string with TSQL

I am trying to sort a string such as '3,9,6' to '3,6,9' with TSQL. My approach was extracting the characters from the string, casting them as integers and putting them into a #temptable using a primary key for sorting. For this I created this procedure:
create proc sortstring(#string varchar(50))
as
declare #limit int = len(#string)
declare #counter int = 1
declare #temps char
create table #temptable (tempstring varchar(30) primary key)
while #counter<=#limit
begin
set #temps = SUBSTRING(#string,#counter,1)
if(#temps!=',')
insert into #temptable values (CAST(#temps as int))
set #counter= #counter+1
end
After this process, I was thinking to extract the integers from #temptable with a while loop to create the sorted string format '3,6'9'. But I think my whole approach is not performance efficient.
Any suggestions?
Below method should be a bit better than the while loop
declare #string varchar(255) = '3,9,6,0,5,12,88,15,23,45,77,88,125,1'
declare #TableList table (tmpStr int)
DECLARE #XML XML
SET #XML = '<root><csv>' + replace(#string, ',', '</csv><csv>') + '</csv></root>'
INSERT #TableList
SELECT replace(Word.value('.', 'integer'), CHAR(10), '')
FROM #XML.nodes('/root/csv') AS WordList(Word)
select * from #TableList order by 1
go
IF OBJECT_ID('tempdb.dbo.#TableList') IS NOT NULL
DROP TABLE #TableList
create table #TableList (tmpStr int)
declare #string varchar(255) = '3,9,6,0,5,12,88,15,23,45,77,88,125,1'
SET #string = 'SELECT ' + REPLACE(#string,',',' UNION ALL SELECT ')
SET #string='INSERT INTO #TableList (tmpStr) ' + #string
EXEC( #string)
SELECT * FROM #TableList ORDER BY tmpStr
Its not a conventional approach but it runs fast.

how to write procedure to add where clause dynamically in mysql

I want to write the store procedure in mysql where I want to add "where clause"
dynamically
I have written the Sp but Its Giving an error
Please Help
CREATE PROCEDURE GetStudent(
#Center varchar(20)=null,
#Gender varchar(20) = null,
#yrOf10 date= null,
#Designation varchar(20)= null,)
AS DECLARE #Query VARCHAR(100);DECLARE #ParamDefinition NVARCHAR(2000);
SET #Query = ' SELECT * FROM Student WHERE 1=1';IF #Center IS NOT NULL
SET #Query = #Query + ' AND Center= #Center ';IF #Gender IS NOT NULL SET #Query = #Query + ' AND Gender=#Gender ';IF #yrOf10 IS NOT NULL SET #Query = #Query + ' AND yrOfPassing10=#yrOf10 ';IF #Designation IS NOT NULL SET #Query = #Query + ' AND Designation=#Designation';
You can not use the # sign in an object name http://dev.mysql.com/doc/refman/5.0/en/identifiers.html.
I don't know why you have prefixed everything with #. Did you start out with MS SQL or something?
Anyway to decalre a local var you use DECLARE http://dev.mysql.com/doc/refman/5.0/en/declare-local-variable.html

How to get initials from fullname in MySQL?

I have a simple table:
id | fullname
---------------------------
1 | Ivanov Ivan Ivanovich
---------------------------
2 | Petrov Petr Petrovich
---------------------------
3 | Alym kyzy Ainura
I need transform them into something like this:
id | name_initials
--------------------
1 | Ivanov I. I.
--------------------
2 | Petrov P. P.
--------------------
3 | Alym k. A.
I can easily make it via PHP, but MySQL is about data manipulation. I think, it might (and MUST) be done with DBMS only.
How can it be done via pure SQL?
Should I write stored function for this, or is there any shorter way?
Regards.
You could use a query like this:
SELECT
fullname,
CONCAT_WS(' ',
SUBSTRING_INDEX(fullname, ' ', 1),
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>2 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -3), 1), '.')
END,
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>1 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -2), 1), '.')
END,
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>0 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -1), 1), '.')
END) shortname
FROM
Names
Please see fiddle here. This query will support at maximum four names.
Solved with stored function:
CREATE FUNCTION `getNameInitials`(`fullname` VARCHAR(70))
RETURNS VARCHAR(70)
DETERMINISTIC
BEGIN
DECLARE `result` VARCHAR(70) DEFAULT '';
DECLARE `position` TINYINT;
DECLARE `separator` VARCHAR(1) DEFAULT ' ';
DECLARE `append` VARCHAR(1) DEFAULT '.';
DECLARE `buffer` VARCHAR(10);
SET `fullname` = CONCAT(TRIM(`fullname`), `separator`);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position`
THEN RETURN TRIM(`fullname`);
END IF;
SET `result` = LEFT(`fullname`, `position` - 1);
cycle: LOOP
SET `fullname` = SUBSTR(`fullname`, `position` + 1);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position` OR NOT LENGTH(`fullname`)
THEN LEAVE cycle;
END IF;
SET `buffer` = CONCAT(LEFT(`fullname`, 1), `append`);
SET `result` = CONCAT_WS(`separator`, `result`, `buffer`);
END LOOP cycle;
RETURN `result`;
END
Checked with:
SELECT
getNameInitials(`fullname`) as `name`
FROM
(
SELECT
'Ivanov Ivan Ivanovich' as `fullname`
UNION ALL
SELECT 'Alym kyzy Ainura'
) `sub`;
And got following result:
'Ivanov I. I.'
'Alym k. A.'
CREATE DEFINER=`root`#`localhost` FUNCTION `getNameInitials`(`fullname` VARCHAR(500), `separator` VARCHAR(1)) RETURNS varchar(70) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE `result` VARCHAR(500) DEFAULT '';
DECLARE `position` TINYINT;
SET `fullname` = TRIM(`fullname`);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position`
THEN RETURN LEFT(`fullname`,1);
END IF;
SET `fullname` = CONCAT(`fullname`,`separator`);
SET `result` = LEFT(`fullname`, 1);
cycle: LOOP
SET `fullname` = SUBSTR(`fullname`, `position` + 1);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position` OR NOT LENGTH(`fullname`)
THEN LEAVE cycle;
END IF;
SET `result` = CONCAT(`result`,LEFT(`fullname`, 1));
-- SET `result` = CONCAT_WS(`separator`, `result`, `buffer`);
END LOOP cycle;
RETURN upper(`result`);
END
1.Execute this function in mysql. 2.this will create a function. Now you can use this function anywhere you want.
SELECT `getNameInitials`('Kaleem Ul Hassan', ' ') AS `NameInitials`;
The above getNameInitails first parameter is string you want to filter and second is the spectator character on which you want to separate you string. 4. In above example 'Kaleem Ul Hassan' is name and i want to get initials and my separator is space ' '.

how to use openrowset to execute a stored procedure with parameters

I'm creating a stored procedure which gets some parameters and in turn these parameters are sent to another stored procedure which I'm calling from openrowset but I'm getting some syntax errors.
CREATE PROCEDURE UpdatePrevFYConfigData
-- Add the parameters for the stored procedure here
#startDate datetime,
#endDate datetime,
#productGroup varchar(8000) = 'All',
#projectType varchar(500) = 'All',
#businessUnit nvarchar(50) = 'All',
#developmentLocation nvarchar(100) = 'All'
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #start varchar(50)
declare #end varchar(50)
set #start = cast(#startDate as varchar(40))
set #end = cast(#endDate as varchar(40))
-- Insert statements for procedure here
select round(avg(a.DeviationDeadline),2) as DeviationDeadline,
round(avg(a.DeviationDefinition),2) as DeviationDefinition,
round(avg(a.DeviationRDCosts),2) as DeviationRDCosts,
round(avg(a.FunctionsAdded) + avg(a.FunctionsDeleted),2) as NotRealizedFuncs,
round(avg(a.DeviationPM2000Aufwand),2) as DeviationPM200Aufwand,
round(avg(b.Defect),2) as Defect
into #tempTable
from openrowset('SQLNCLI',
'Server=.\sqlexpress;Trusted_Connection=yes;',
'SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.SelectScorecardGraphData
'''+#start+''',
'''+#end+''',
'''+#productGroup+''',
'''+#projectType+''',
''1'',
''0'',
''All'',
''Current'',
'''+#businessUnit+''',
'''+#developmentLocation+'''
') as a,
openrowset('SQLNCLI', 'Server=.\sqlexpress;Trusted_Connection=yes;', 'SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.GetSPCDefectDistributionData
'''+cast(#startDate as varchar(40))+''',
'''+cast(#endDate as varchar(40))+''',
''Defect'',
'''+#projectType+''',
'''+#productGroup+''',
'''+#businessUnit+''',
'''+#developmentLocation+'''') as b
update dbo.EA_ProcessScorecard_Config_Tbl
set EPC_Deviation = case EPC_Metric
when 'PM200' then (select DeviationDefinition from #tempTable)
when 'PM300' then (select DeviationDeadline from #tempTable)
when 'Cost' then (select DeviationRDCosts from #tempTable)
when 'PM150' then (select DeviationPM200Aufwand from #tempTable)
when 'Defect' then (select Defect from #tempTable)
when 'Funcs' then (select NotRealizedFuncs from #tempTable)
END
where EPC_Description = 'PrevFY' and EPC_FYYear = '0'
drop table #tempTable
END
GO
I'm not able to create it and I get the error message:
Msg 102, Level 15, State 1, Procedure UpdatePrevFYConfigData,
Line 38 Incorrect syntax near '+'.
... but if I use hard coded values for the parameters it works!!
Please help!
Both OPENROWSET and OPENDATASOURCE should be used only for accessing external data for, let's say, quick and dirty solutions, or when it is not possible to configure a permanent linked server. These functions do not provide all of the functionality available from a linked server.
The arguments of OPENROWSET and OPENDATASOURCE do not support variables. They have to be specified as string-literal. If variables need to be passed in as arguments to these functions, a query string containing these variables can be constructed dynamically and executed using the EXEC statement.
Similar to (not syntax checked)
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = 'SELECT *
FROM OPENROWSET(''SQLNCLI'',''server=.\sqlexpress;Trusted_Connection=yes'',''SET NOCOUNT ON;SET FMTONLY OFF;EXEC [BSC_DB].dbo.SelectScorecardGraphData ''''' + cast(#param1 as varchar(10)) + ''''',''' + cast(#param2 as varchar(n)) ''')'
EXEC #sqlCommand
And so on...
Hope that helps. Kind regards,
Stefan
-- FOR USING OPENROWSETS
EXEC sp_configure 'Ad Hoc Distributed Queries'
,1
RECONFIGURE
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'INSERT INTO #TABLESIZESYEAR SELECT NULL AS [TABLE NAME], * FROM OPENROWSET
(''SQLOLEDB'',''Server=(local);TRUSTED_CONNECTION=YES;'',''set fmtonly off EXEC one.[dbo].[InvestigateDataGrowthByYearAndClient] #pDATECOLUMN =' + #YEARCOLUMN + ' ,
#pTABLENAME = ' + #TABLENAME + ' WITH RESULT SETS(
([YEAR NAME] NVARCHAR(5) NULL
, [NUMBER OF ROWS] CHAR(11)
, [RESERVED SPACE] VARCHAR(18)
, [DATA SPACE] VARCHAR(18)
, [INDEX SIZE] VARCHAR(18)
, [UNUSED SPACE] VARCHAR(18) )
)
;'') '
DECLARE #ParmDefinition NVARCHAR(500) = '#pDATECOLUMN NVARCHAR(20)
,#YEARCOLUMN NVARCHAR(20)
,#pTABLENAME NVARCHAR(60)';
EXECUTE sp_executesql #sql
,#ParmDefinition
,#YEARCOLUMN = #YEARCOLUMN
,#pDATECOLUMN = #YEARCOLUMN
,#pTABLENAME = #TABLENAME