Crystal reports and stored procedures - crystal-reports

I'm new at Crystal Reports and still learning so I'm wondering how I should do this. I have the following stored procedure:
CREATE PROCEDURE GetSurveyAnswerDetail
(#Question VARCHAR(255) = NULL, #AllowReportFlag CHAR(1) = NULL)
AS
SET NOCOUNT ON
DECLARE #rc INT
SET #rc = 1
IF (#Question IS NULL OR DATALENGTH(#Question) = 0
OR #AllowReportFlag IS NULL OR DATALENGTH(#AllowReportFlag) = 0)
RAISERROR('GetSurveyAnswerDetail is missing parameters.', 16, 1)
ELSE
BEGIN
DECLARE #AllowReport VARCHAR(100)
IF (#AllowReportFlag = 'N')
SET #AllowReport = ' AllowReport = ''Y'' AND '
ELSE
SET #AllowReport = ''
DECLARE #SQLStatement VARCHAR(5000)
SET #SQLStatement = 'SELECT COUNT(' + #Question + ') FROM tblSurveyAnswer WHERE ' + #AllowReport + #Question + ' != '''' GROUP BY ' + #Question + ' ORDER BY ' + #Question + ' DESC'
EXEC (#SQLStatement)
IF ##ERROR <> 0
RAISERROR('GetSurveyAnswerDetail has failed. Question may not exist.', 16, 1)
ELSE
SET #rc = 0
END
RETURN #rc
GO
This returns a list of numbers. What I'd like to do is create a pie chart from these numbers in Crystal Reports. I know you can set your data source from a stored procedure but when I do this, there are no fields I can choose. I'm probably going about this the wrong way so I'd appreciate any comments.

Michael, try making your stored procedure return a table. My guess is that you don't see any fields because you aren't returning any. Change the return line to
SELECT #rc AS Result
This should show you the Result as a field in the Report. I'm not sure that you can run the proc individually on a loop to manufacture a pie-chart. You may need to return all the data you want out of one stored procedure.

There must be a select query that is not hiding behind an if statement.
If you stored procedure is:
If #question = 'Y'
begin
SET #SQLStatement = 'select field from table where condition='OK'
EXEC (#SQLStatement)
end
In this example no fields will be shown. Change it to:
If #question = 'Y'
begin
SET #SQLStatement = 'select field from table where condition='OK'
end
else
Begin
select field from table where condition='impossiblecondition'
end
In this example it will work and fields will be shown.
I create a dummy parameter like #question and pass the 'Y'.

Related

Access pass-through query passing comma separated list as a parameter to SQL stored procedure

The SQL server is 2008. I have an Access 2016 front-end for reporting purposes. One report requires that one or more Product Classes from a list be chosen to report on. I have the VBA that creates the pass-through query with the appropriate single line:
exec dbo.uspINVDAYS 'A3,A4,A6,AA,AB'
I have this SQL code that should take the list as hard-coded here:
DECLARE #parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE #ProductClasses NVARCHAR(200),#delimiter NVARCHAR(1) = ',';
SET #ProductClasses = #parProductClasses;
DECLARE #DAYS INT,#numDAYS int;
SET #DAYS = 395;
SET #numDAYS = #DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,#numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass IN (Select val From TablesCoE.dbo.split(#ProductClasses,','));
When I run this I get:
Msg 468, Level 16, State 9, Line 9
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_BIN" in the equal to operation.
I cannot determine where
COLLATE SQL_Latin1_General_CP1_CI_AS
should go. Where am I equating or comparing? The SQL IN clause cannot handle the comma-separated list since it is not a strict SQL table.
Here's the code used to create the dbo.split() function:
CREATE FUNCTION dbo.split(
#delimited NVARCHAR(MAX),
#delimiter NVARCHAR(100)
) RETURNS #t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE #xml XML
SET #xml = N'<t>' + REPLACE(#delimited,#delimiter,'</t><t>') + '</t>'
INSERT INTO #t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM #xml.nodes('/t') as records(r)
RETURN
END
Thanks to Sandeep Mittal and I am sure others have very similar split functions. Run separately this function does operate as expected and provides a table of the comma-separated list objects.
DECLARE #parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE #ProductClasses NVARCHAR(200),#delimiter NVARCHAR(1) = ',';
SET #ProductClasses = #parProductClasses;
Select val From TablesCoE.dbo.split(#ProductClasses,',')
Returns
val
A3
A4
A6
AA
AB
try this.
WHERE concat(',',#ProductClasses,',') like concat('%',UPINVENTORY.ProductClass,'%')
it's a silly way of checking if your productClass is within the #productClasses list.
After attempting to use a prefabricated table-valued variable versus on the fly in the WHERE clause, neither worked, I then started to try different placements of the COLLATE statement. I was complacent in applying COLLATE to the right-side with the collation listed on the left in the SQL error message. I tried the collation listed on the right of the SQL error message to the left side of the WHERE clause and the SQL code works to spec now. Here it is:
DECLARE #parProductClasses NVARCHAR(200) = 'A3,A4,A6,AA,AB';
DECLARE #ProductClasses NVARCHAR(200),#delimiter NVARCHAR(1) = ',';
SET #ProductClasses = #parProductClasses;
DECLARE #DAYS INT,#numDAYS int;
SET #DAYS = 395;
SET #numDAYS = #DAYS;
SELECT UPINVENTORY.StockCode, UPINVENTORY.[Description], UPINVENTORY.Supplier, UPINVENTORY.ProductClass
, UPINVENTORY.WarehouseToUse
, CAST(UPINVENTORY.Ebq AS INT)Ebq
, cast(UPINVENTORY.QtyOnHand AS INT)QtyOnHand
, cast(UPINVENTORY.PrevYearQtySold AS INT)PrevYearQtySold
, cast(UPINVENTORY.YtdQtyIssued AS INT)YtdQtyIssued
,#numDAYS as numDAYS
,CAST(ROUND((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS,0) AS INT)TOTAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS),0)AS INT)
END FINAL
,CASE WHEN (PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS
= 0 THEN 0
ELSE CAST(ROUND(QTYONHAND/((PREVYEARQTYSOLD + YTDQTYISSUED)/#DAYS),0)AS INT)
END FINAL1
FROM
TablesCoE.dbo.vwRPUpInventory UPINVENTORY
WHERE UPINVENTORY.ProductClass COLLATE Latin1_General_BIN IN (SELECT val FROM TablesCoE.dbo.split(#ProductClasses,','));
Thanks for your suggestions #Krish and #Isaac.
Tim

postgresql execute dynamic sql command

I'm slowly learning more about PostgreSQL, as we are attempting to move to it from MSSQL Server.
In MSSQL I have the following code:
DECLARE ServiceabilityParameters
CURSOR FORWARD_ONLY READ_ONLY STATIC LOCAL FOR
SELECT WorkbookParameterType.ID,
WorkbookParameterType.Name,
WorkbookParameter.DefaultValue,
WorkbookParameter.CommandText
FROM WorkbookParameter
JOIN WorkbookParameterType ON WorkbookParameterType.ID = WorkbookParameter.WorkbookParameterTypeID
JOIN WorkbookParameterDirectionType ON WorkbookParameterDirectionType.ID = WorkbookParameter.WorkbookParameterDirectionTypeID
AND WorkbookParameterDirectionType.Writable = 1
WHERE WorkbookParameter.WorkbookID = #WorkbookID
OPEN ServiceabilityParameters
FETCH NEXT FROM ServiceabilityParameters INTO #WorkbookParameterTypeID, #WorkbookParameterTypeName, #WorkbookDefaultValue, #WorkbookCommandText
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #ActualValue NVARCHAR(256) = NULL
IF #WorkbookCommandText IS NOT NULL
BEGIN
EXEC sp_executesql #statement = #WorkbookCommandText,
#params = N'#ApplicationContainerID INT, #Value NVARCHAR(256) OUTPUT',
#ApplicationContainerID = #ApplicationContainerID,
#Value = #ActualValue OUTPUT
END
IF #ActualValue IS NULL AND #WorkbookDefaultValue IS NOT NULL
BEGIN
SET #ActualValue = #WorkbookDefaultValue
END
INSERT #InputParameters (
ID, Name, Value
) VALUES (
#WorkbookParameterTypeID, #WorkbookParameterTypeName, #ActualValue
)
FETCH NEXT FROM ServiceabilityParameters INTO #WorkbookParameterTypeID, #WorkbookParameterTypeName, #WorkbookDefaultValue, #WorkbookCommandText
END
CLOSE ServiceabilityParameters
DEALLOCATE ServiceabilityParameters
I'm trying to work out how to do the sp_executesql part in a PostgreSQL function. I believe that I can do the rest, but most of the examples that I have found show a simple select with maybe a few variables, whereas I need to execute another function, with parameters, where the function name is text in a table.
Many Thanks.
In case you want to execute a function with parameters
EXECUTE 'SELECT Value FROM ' || v_workbookCommandText || '(ApplicationContainerID :=$1)'
INTO v_actualValue
USING v_applicationContainerID;
In case you need select records a function, you can using INOUT refcursor variable
EXECUTE 'SELECT Value FROM ' || v_workbookCommandText || '(ApplicationContainerID :=$1, refcur:= $2)'
INTO v_actualValue
USING v_applicationContainerID, my_cursor;
I think what you want to do is EXECUTE 'some string', like this:
EXECUTE 'SELECT count(*) FROM mytable WHERE inserted_by = $1 AND inserted <= $2'
INTO c
USING checked_user, checked_date;
Another option is to create and use your own PL/PGSQL functions.

Dynamic SQL with nvarchar(max) variable (again)

I have read about a dozen articles here and I am still stumped with this issue.
I am building a dynamic select statement that will update a view on a monthly schedule.
set ansi_nulls on
go
set quoted_identifier on
go
alter procedure [dbo].[Proc_Name_SP]
as
begin
set nocount on
set quoted_identifier off
declare #dbname varchar(10), #schema_id int, #schema_name varchar(10),
#jacro varchar(10), #rec_cnt int, #tot_rec int
declare #SQL_Main nvarchar(max), #SQL_Final nvarchar(max),
#SQL_schema nvarchar(2000), #SQL_Union nvarchar(max)
declare iteration cursor global static for
-- Begin statement for cursor array
select distinct db, code
from linkedserver.db.schema.Directory
where current_stage = 'live'
order by db
-- End statement for cursor array
-- get total number of cursor iterations to know when to stop
-- "union" statements
select #tot_rec = count(*) from (select distinct db, code
from [linkedserver].db.schema.Directory
where current_stage = 'live') as cur
-- begin loop
open iteration
fetch first from iteration into #dbname, #jacro
while ##fetch_status=0
begin
-- the schema used is not consistent. Because of the linked server it was
-- necessary to get the Schema_ID from the sys.tables and then pull the
-- schema name from sys.schema
set #SQL_schema = 'select #sch_id = schema_id from [linkedserver].'+#dbname+'.sys.tables where name = ''Manuscript'''
execute sp_executesql #SQL_schema, N'#sch_id int OUTPUT', #sch_id = #schema_id output
--print #schema_id
set #SQL_schema ='select #sch_name = name from [linkedserver].'+#dbname+'.sys.schemas where schema_id = '+cast(#schema_id as varchar)+''
execute sp_executesql #SQL_schema, N'#sch_name nvarchar(10) OUTPUT', #sch_name = #schema_name output
--print #schema_name
--building Select statement
set #SQL_Main ='
select jcode.Code as BILLING_ACRO
,s.start_dt as BILLING_DATE
,cmpt_ms_nm as MANUSCRIPT
,isnull(jcode.billing_type, ''reviewed'') as Billing_type
from [linkedserver].'+#dbname+'.'+#schema_name+'.Manuscript as m
join [linkedserver].'+#dbname+'.'+#schema_name+'.Step as s on m.ms_id = s.ms_id and m.ms_rev_no = s.ms_rev_no
join (select j_id, Code, billing_type from [linkedserver].db.schema.Directory where db = '''+#dbname+''') as jcode on jcode.j_id = m.j_id
where jcode.Code = '''+#jacro+'''
and m.ms_rev_no = 0
and s.stage_id = 190
and isnull(cmpt_ms_nm, '''') <> ''''
and s.step_id = (select min(s2.step_id)
from [linkedserver].'+#dbname+'.'+#schema_name+'.Step as s2
where s2.stage_id = 190
and s2.ms_id = m.ms_id
and s2.ms_rev_no = m.ms_rev_no)
'
set #rec_cnt = isnull(#rec_cnt, 0) + 1
if #SQL_Union is null
begin
set #SQL_Union = #SQL_Main
end
else if #tot_rec <> #rec_cnt
begin
set #SQL_Union = #SQL_Union + ' union ' + #SQL_Main
end
else
begin
set #SQL_Union = #SQL_Union + #SQL_Main
end
--print #rec_cnt
fetch next from iteration into #dbname, #jacro --next database
end -- while ##FETCH_STATUS=0
close iteration
deallocate iteration
-- build new view
print len(#SQL_Union)
set #SQL_Final = '
ALTER VIEW [dbo].[View_Name_VW]
AS
'+#SQL_Union+'
'
execute sp_executesql #SQL_Final
--grab string variables to table for troubleshooting
insert into Output_SQL(SQL_Final, SQL_Final_Len, SQL_Union, SQL_Union_Len)
select #SQL_Final, LEN(#SQL_Final), #SQL_Union, LEN(#SQL_Union)
set nocount off
end
go
I have read that others have had problems with this type of truncation and I have tried multiple suggestions but in the end the I am getting capped at 68274 in this code with nvarchar(max). For troubleshooting, I am saving the results of the variables and the len of these variables to a table to eliminate the SSMS cap on the display of strings.
I have tried cast(#varible as nvarchar(max)) on the right side of the = sign. I have changed the data type lengths (as the select that is being built is not that large, it is just large after it has been union for each unique customer)
I am open to any suggestions as I have tried many variations of datatype declarations for these variables.

Is a T-SQL conditional TOP clause possible?

I want to dynamically use TOP or not sort of like this...
SELECT #SomeNumber CASE WHERE 0 THEN TOP 5 COLUMNNAME
ELSE COLUMNNAME
END
FROM TABLE
I hope to have understood your problem: you want to select the TOP 5 rows if you pass #SomeNumber = 0 else select all th etable rows
As a first straight implementation you can do something like that
declare #SomeNumber as int
set #SomeNumber = 5
-- set #SomeNumber = 1
SELECT TOP (SELECT #SomeNumber) COLUMNNAME FROM MYTABLE
you can change the parameter value in order to have how many rows you want
Otherwise i suggest you to implement a stored procedure (and maybe you already did that, otherwise you can follow the next steps in order to do it)
CREATE procedure [dbo].[TOPCLAUSE]
-- clause parameter
#SomeNumber as integer
AS
IF #SomeNumber = 0
BEGIN
SELECT TOP 5 COLUMNNAME FROM MYTABLE
END
ELSE
BEGIN
SELECT COLUMNNAME FROM MYTABLE
END
GO
Then you can call
exec [dbo].[TOPCLAUSE] 0
exec [dbo].[TOPCLAUSE] 1
I probably not answered your question but let me know if it helped you
I don't think you can.
You could either use dynamic SQL:
Declare #int int
set #int = 10
exec ('Select top ' + #int + ' * From Customers')
Or you could set rowcount
if (#someNumber != 0)
begin
set rowcount 5
end
select * From Customers
set rowcount 0
I've just used something like this:-
Declare #SQL nvarchar(max), #Params nvarchar(max)
set #Params = N''
Set #SQL = N'SELECT ' + Cast(#SomeNumber as varchar) + ' CASE WHERE 0 THEN TOP 5 COLUMNNAME
ELSE COLUMNNAME
END
FROM TABLE'
exec sp_executesql #SQL, #Params
Short answer is no, not the way you have it.
You can however use IF to test and run a different query:
IF (#SomeNumber = 0)
BEGIN
SELECT TOP 5 ColumnName FROM Table
END
ELSE
BEGIN
SELECT ColumnName FROM Table
END
Two options: conditional SQL or dynamic SQL.
(1) Conditional:
IF #SomeNumber = 0
SELECT TOP 5 COLUMNAME FROM TABLE
ELSE
SELECT COLUMNAME FROM TABLE
(2) Dynamic: build up the query in a varchar() and pass it to sp_execute
Another loophole: make use of subquery's with row_number function
DECLARE #DoTopJN AS bit
SET #DoTopJN = 0 -- or 1
SELECT X.Sequence
X.COLUMNA
--etc
FROM (SELECT ROW_NUMBER() OVER (ORDER BY Y.Code) AS Sequence
,Y.COLUMNA
,Y.COLUMNB
-- etc.
FROM Y) X
WHERE ((#DoTopJN = 0) OR (X.Sequence = 1))
I don't think this is possible because TOP is applied on not just a column but the whole row. You would have to create two different select statements and put them in a IF ELSE construct.
To correct SPE109's code:
DECLARE #SomeNumber INT = 0
DECLARE #SQL nvarchar(max), #Params nvarchar(max)
set #Params = N''
SELECT #SQL = N'SELECT ' + CASE WHEN #SomeNumber = 0 THEN '' ELSE 'TOP ' + CAST(#SomeNumber as varchar) END + ' COLUMNNAME FROM TABLE'
exec sp_executesql #SQL, #Params

Try-Catch in User Defined Function?

I'm trying to write a UDF to translate a string that is either a guid or a project code associated with that guid into the guid:
CREATE FUNCTION fn_user_GetProjectID
(
#Project nvarchar(50)
)
RETURNS uniqueidentifier
AS
BEGIN
declare #ProjectID uniqueidentifier
BEGIN TRY
set #ProjectID = cast(#Project as uniqueidentifier)
END TRY
BEGIN CATCH
set #ProjectID = null
END CATCH
if(#ProjectID is null)
BEGIN
select #ProjectID = ProjectID from Project where projectcode = #Project
END
return #ProjectID
END
This works fine if the above code is embedded in my Stored Procedures, but I'd like to make a function out of it so that I follow DRY.
When I try to create the Function, I get errors like this:
Msg 443, Level 16, State 14, Procedure fn_user_GetProjectID, Line 16
Invalid use of side-effecting or time-dependent operator in 'BEGIN TRY' within a function.
Does anyone have an idea how I can get around this error?
Edit: I know I can't use Try-Catch in a Function, I guess a simplified questions would be, is there a way to do a cast that will just return NULL if the cast fails, instead of an error?
Apparently you can't use TRY-CATCH in a UDF.
According to this bug-reporting page for SQL Server:
Books Online documents this behaviour,
in topic "CREATE FUNCTION
(Transact-SQL)": "The following
statements are valid in a function:
[...] Control-of-Flow statements
except TRY...CATCH statements. [...]"
But they were giving hope for the future back in 2006:
However, this is a severe limitation
that should be removed in a future
release. You should post a suggestion
in this regard and I will
wholeheartedly vote for it.
From MSDN:
A column or local variable of
uniqueidentifier data type can be
initialized to a value in the
following ways:
By using the NEWID function.
By converting from a string constant
in the form
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,
in which each x is a hexadecimal digit
in the range 0-9 or a-f.
For example,
6F9619FF-8B86-D011-B42D-00C04FC964FF
is a valid uniqueidentifier value.
You can use pattern matching to verify the string. Note that this won't work for specific encoding that reduces the size of the GUID:
declare #Project nvarchar(50)
declare #ProjectID uniqueidentifier
declare #HexPattern nvarchar(268)
set #HexPattern =
'[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' +
'[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' +
'[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' +
'[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]'
/* Take into account GUID can have curly-brackets or be missing dashes */
/* Note: this will not work for GUIDs that have been specially encoded */
set #Project = '{' + CAST(NEWID() AS VARCHAR(36)) + '}'
select #Project
set #Project = REPLACE(REPLACE(REPLACE(#Project,'{',''),'}',''),'-','')
/* Cast as uniqueid if pattern matches, otherwise return null */
if #Project LIKE #HexPattern
select #ProjectID = CAST(
SUBSTRING(#Project,1,8) + '-' +
SUBSTRING(#Project,9,4) + '-' +
SUBSTRING(#Project,13,4) + '-' +
SUBSTRING(#Project,17,4) + '-' +
SUBSTRING(#Project,21,LEN(#Project)-20)
AS uniqueidentifier)
select #ProjectID
I know I can't use Try-Catch in a Function, I guess a simplified questions would be, is there a way to do a cast that will just return NULL if the cast fails, instead of an error?
Starting from SQL Server 2012 you could use TRY_CAST/TRY_CONVERT functions:
Returns a value cast to the specified data type if the cast succeeds; otherwise, returns null.
CREATE FUNCTION fn_user_GetProjectID(#Project nvarchar(50))
RETURNS uniqueidentifier
AS
BEGIN
declare #ProjectID uniqueidentifier = TRY_CAST(#Project as uniqueidentifier);
IF(#ProjectID is null)
BEGIN
select #ProjectID = ProjectID from Project where projectcode = #Project;
END
return #ProjectID;
END
Not sure, but why not flip it around... at first glance I would simplify it like this:
select #ProjectID =
ISNULL((select ProjectID from Project where
projectcode = #Project)
,(cast #Project as uniqueidentifier))
If this doesn't provide enough error handling, I'm sure there's a better way to pre-check that the cast can work without using try/catch...
My brute force method was to create my own ToGuid() function that verifies it can be converted to a GUID first, if not, it returns null. It may not be very fast but it does the job, and it is probably faster to convert the guid if it is one than to try to look it up in the table. EDIT: I meant to give credit to this blog, where I got the basis of my code for this function: http://jesschadwick.blogspot.com/2007/11/safe-handling-of-uniqueidentifier-in.html
CREATE FUNCTION [dbo].[ToGuid]
(
#input NVARCHAR(MAX)
)
RETURNS uniqueidentifier
AS
BEGIN
DECLARE #isValidGuid BIT;
DECLARE #temp NVARCHAR(MAX);
SET #isValidGuid = 1;
SET #temp = UPPER(LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(#input, '-', ''), '{', ''), '}', ''))));
IF(#temp IS NOT NULL AND LEN(#temp) = 32)
BEGIN
DECLARE #index INT;
SET #index = 1
WHILE (#index <= 32)
BEGIN
IF (SUBSTRING(#temp, #index, 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F'))
BEGIN
SET #index = #index + 1
END
ELSE
BEGIN
SET #isValidGuid = 0
BREAK;
END
END
END
ELSE
BEGIN
SET #isValidGuid = 0
END
DECLARE #ret UNIQUEIDENTIFIER
IF(#isValidGuid = 1)
set #ret = cast(#input AS UNIQUEIDENTIFIER)
ELSE
set #ret = NULL
RETURN #ret
END
I'm still very interested if there is a better answer than this.
Verify if #Project is a number using the ISNUMERIC function.
your code should looks like that:
declare #ProjectID uniqueidentifier
set #ProjectID = null
IF ISNUMERIC(#Project) > 0
BEGIN
set #ProjectID = cast(#Project as uniqueidentifier)
END
if(#ProjectID is null)
BEGIN
select #ProjectID = ProjectID from Project where projectcode = #Project
END
return #ProjectID