I have a emailID column in my database .Which has some numeric value in starting followed by 3 dashes then comes emailID I want to remove the numberic values as well as 3 dashes. which are coming starting from the emailID . The numeric values can be increase or decrease but dashes will remain same.below are the examples
dbo.regexp_replace('128888822229990976---Anand.chaudhary#gmail.com','^(\d+\-{3})','') as email_guess1
dbo.regexp_replace('222299---Anand.chaudhary#gmail.com','^(\d+\-{3})','') as email_guess1
dbo.regexp_replace('45390976---Archit.kumar-bhargav#gmail.com','^(\d+\-{3})','') as email_guess1
dbo.regexp_replace('0042352229990976---shiv.mangal-gupta#gmail.com','^(\d+\-{3})','') as email_guess1
I am using below user defined function its working fine but taking more time because my table has millions of records .. Please help me.
CREATE function [dbo].[regexp_replace] (
--
--
-- These match exactly the parameters of RegExp
--
#searchstring varchar(4000),
#pattern varchar(4000),
#replacestring varchar(4000)
)
returns varchar(4000)
as
begin
declare #objRegexExp int,
#objErrorObj int,
#strErrorMessage varchar(255),
#res int,
#result varchar(4000)
if #searchstring is null or len(ltrim(rtrim(#searchstring))) = 0 begin
return null
end;
set #result='';
exec #res = sp_OACreate 'VBScript.RegExp', #objRegexExp out;
if #res <> 0 begin
return 'VBScript did not initialize!';
end;
exec #res=sp_OASetProperty #objRegexExp, 'Pattern', #pattern;
if #res <> 0 begin
return 'Pattern property set failed!';
end;
exec #res=sp_OASetProperty #objRegexExp, 'IgnoreCase', 0;
exec #res=sp_OASetProperty #objRegexExp, 'global', 1;
if #res <> 0 begin
return 'IgnoreCase option failed!';
end;
exec #res=sp_OAMethod #objRegexExp, 'Replace', #result out, #searchstring, #replacestring;
if #res <> 0 begin
return 'Bad search string!';
end;
exec #res=sp_OADestroy #objRegexExp;
return #result
end;
It is too expensive to use VB COM objects in your queries.
Here you can use RIGHT, LEN and CHARINDEX to achieve that:
CREATE TABLE t (email varchar(100)) ;
INSERT INTO t (email)
VALUES ('123---Anand.chaudhary#gmail.com') ;
SELECT RIGHT(email, LEN(email) - CHARINDEX('---', email) - 2) as email
FROM t ;
So your function would be:
CREATE function [dbo].[fn_email] (
#email varchar(200), -- I beleive there won't be email addresses longer than 200 chars
)
returns varchar(200)
as
begin
SELECT RIGHT(#email, LEN(#email) - CHARINDEX('---', #email) - 2)
end
Related
How to fetch the code comments from a stored procedure / function and populate to a table?
/*
Author : Test
Comment : Test
*/
I am working on a user defined function by passing either a stored procedure or function as input parameter to read the code history comments and store it in a table. Having the detail in a table to maintain the version notes for the input.
Check this, there are different ways to get the definition, I prefer sp_helptext because it's already splitted in lines
DECLARE #Objects TABLE(name varchar(100))
DECLARE #Lines TABLE(id int identity, line varchar(maX))
INSERT #Objects
SELECT name FROM sys.objects WHERE Type in ('FN', 'IF', 'P', 'TR', 'TF')
DECLARE #ObjectName VARCHAR(100)
WHILE EXISTS (SELECT 1 FROM #Objects)
BEGIN
SELECT TOP 1 #ObjectName = name FROM #Objects
DELETE #Lines
INSERT #Lines (line)
exec sp_helptext #ObjectName
DECLARE #Linestart INT, #LineEnd INT
WHILE EXISTS(SELECT 1 FROM #Lines WHERE charindex('/*', line) > 0)
BEGIN
SELECT TOP 1 #Linestart = id
FROM #Lines WHERE charindex('/*', line) > 0
ORDER BY id
SELECT TOP 1 #LineEnd = id
FROM #Lines WHERE charindex('*/', line) > 0
ORDER BY id
DECLARE #comment VARCHAR(MAX) = ''
SELECT #Coment = #coment + char(13) + char(10) + line
FROM #Lines
WHERE id between #LineStart and #lineEnd
INSERT INTO yourtable (#objectName, #Comment)
DELETE #Lines WHERE id between #LineStart and #lineEnd
END
DELETE #Objects WHERE name = #ObjectName
END
You can create a function/stored procedure to achieve this:
CREATE FUNCTION InsertCommentIntoTable
(
#Param1 VARCHAR(200)
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE #str VARCHAR(max)
SELECT #str = definition
FROM sys.sql_modules
WHERE object_id = (OBJECT_ID(N'dbo.CustOrderHist'));
--parse #str string value and do your stuffs: #str has the function and stored procedure codes.
RETURN 0;
END
GO
I have a function which I have created in SQL but I am getting this error 'SQL server issue - Create Function must be the only statement in the batch'. I checked other similar topics but couldn't find anything wrong. I am using SQL Server 2012
CREATE FUNCTION GETLLPATH(#objectid FLOAT)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #dir VARCHAR(MAX);
DECLARE #obj_id FLOAT;
DECLARE Name_Cursor CURSOR LOCAL FOR
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A
WHERE A.DataID = #obj_id;
DECLARE
SET #dir = NULL;
SET #obj_id = #objectid;
WHILE 1=1 BEGIN
OPEN Name_Cursor;
FETCH Name_Cursor INTO #name;
IF ##FETCH_STATUS <> 0 BREAK or #name_NAME = 'Enterprise';
IF #dir IS NOT NULL BEGIN
SET #dir = (ISNULL(#name_NAME, '') + ':' + isnull(#dir, '')) ;
END
IF #dir IS NULL BEGIN
SET #dir = #name_NAME;
END
SET #obj_id = #name_PARENTID;
CLOSE Name_Cursor;
DEALLOCATE Name_Cursor;
END;
return(#dir);
END;
GO
I am also getting error for variables as 'Must declare Scalar variable', In the end there is one more error - 'Expecting conversation', request you to please help.
I believe you just have some bad code.
Try this:
CREATE FUNCTION GETLLPATH(
#objectid FLOAT
)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE #dir VARCHAR(MAX);
DECLARE
#obj_id FLOAT
, #name_NAME VARCHAR(50) -- or whatever your field size is.
, #name_PARENTID VARCHAR(50) -- again, whatever your field size is.
DECLARE Name_Cursor CURSOR LOCAL FOR
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A WHERE A.DataID = #obj_id;
SET #dir = NULL; -- redundant.
SET #obj_id = #objectid; -- this can be set at declaration ( e.g. DELARE #obj_id FLOAT = #obj_id ).
WHILE ( 1 = 1 ) BEGIN
OPEN Name_Cursor;
FETCH Name_Cursor INTO #name;
IF ( ##FETCH_STATUS <> 0 OR #name_NAME = 'Enterprise' )
BREAK;
IF ( #dir IS NOT NULL ) BEGIN
SET #dir = (ISNULL(#name_NAME, '') + ':' + isnull(#dir, '')) ;
END
IF #dir IS NULL BEGIN
SET #dir = #name_NAME;
END
SET #obj_id = #name_PARENTID;
CLOSE Name_Cursor;
DEALLOCATE Name_Cursor;
END
RETURN #dir;
END
GO
On a personal note, I am never fond of using WHILE (1=1). Are you guaranteed to have an exit?
Also, I would highly recommend using an alternative to a cursor. Perhaps use a TABLE variable and loop through that like so:
CREATE FUNCTION GETLLPATH(
#objectid FLOAT
)
RETURNS VARCHAR(4000)
AS
BEGIN
-- declare variables --
DECLARE #id INT
, #dir VARCHAR(MAX)
, #obj_id FLOAT = #objectid
, #name_NAME VARCHAR(50)
, #name_PARENTID VARCHAR(50)
-- declare table variable --
DECLARE #data TABLE( [name] VARCHAR(50), [parent_id] VARCHAR(50), [id] INT IDENTITY (1,1) );
-- insert data --
INSERT INTO #data ( [name], [parent_id] )
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A WHERE A.DataID = #obj_id;
-- for-each row... --
SET #id = 1;
WHILE ( #id <= ( SELECT MAX( id ) FROM #data ) )
BEGIN
-- current row --
SELECT
#name_NAME = [name]
, #name_PARENTID = [parent_id]
FROM #data WHERE [id] = #id;
-- do your work here...
-- next row --
SET #id = ( #id + 1 );
END
RETURN #dir;
END
GO
There are a couple of syntax errors even before I test your query:
The word 'DECLARE' should not appear in the middle without a variable name,
#name_Name and #name_PARENTID are undeclared
DECLARE #name_NAME varchar, #name_PARENTID int
(check for the variable types according to the source table)
IF ##FETCH_STATUS <> 0 BREAK or #name_NAME = 'Enterprise' is incorrect
IF ##FETCH_STATUS <> 0 or #name_NAME = 'Enterprise'
BREAK
"Create Function must be the only statement in the batch" - usually
means there is some syntax error.
This is, honestly, a total guess, and (most importantly) completely untested; due to the absence of sample data and expected results.
Anyway, like I said in the comments, a CURSOR and a Scalar-value Function are both really bad performers here. If you're trying to simply delimit your data with a colon (:), then you can use STUFF and FOR XML PATH.
Like I said, this is completed untested, but might get you on the right path:
CREATE FUNCTION dbo.GetllPath (#objectID int) --Is it really a float? I've used an int
RETURNS table
AS RETURN
SELECT STUFF((SELECT ':' + DT.[Name]
FROM OTCS_User.DTree DT
WHERE DT.DataID = #obj_id
--ORDER BY SOMETHING HERE!!!
FOR XML PATH('')),1,1,'') AS llPath;
GO
I tried to make a function that returns varchar, but I can't because I'm using CREATE TABLE inside, and when I'm creating it with a procedure I can't return a value.
I wanted to know if you have some advice.
I made this just to make a string with emails separated by ";" so I can have all the "manager" mails in one varchar (for the recipients).
ALTER procedure [dbo].[Manager_email]
AS
BEGIN
declare #mails varchar (max),
#number_of_mails int,
#counter int
set #counter=2
create table #temp ( id int identity, email varchar(30))
insert into #temp (email)
select Email
from hr.Employees
where lower (EmpRole) like 'manager'
set #number_of_mails=##ROWCOUNT
set #mails = (select email from #temp where id =1 ) + ';'
while #counter <= #number_of_mails
BEGIN
set #mails = #mails + (select email from #temp where id =#counter ) + ';'
set #counter = #counter+1
END
drop table #temp
return cast (#mails as varchar (200))
END
You can only return integer value back from the procedure, If you want to return varchar value from procedure its good to make use of output variable in procedure.
Example
CREATE PROCEDURE Sales.uspGetEmployeeSalesYTD
#SalesPerson nvarchar(50),
#SalesYTD money OUTPUT
AS
SET NOCOUNT ON;
SELECT #SalesYTD = SalesYTD
FROM Sales.SalesPerson AS sp
JOIN HumanResources.vEmployee AS e ON e.BusinessEntityID = sp.BusinessEntityID
WHERE LastName = #SalesPerson;
RETURN
like in above procedure return #SalesYTD from procedure.
you can check full post on MSDN : Returning Data by Using OUTPUT Parameters
You can use function instead
CREATE FUNCTION Manager_email ()
RETURNS varchar(max)
AS
BEGIN
declare #email varchar(30)
declare #emails varchar(max)
set #emails = ''
declare cur cursor for
select Email
from hr.Employees
where lower (EmpRole) like 'manager'
open cur
fetch next from cur into #email
while ##fetch_status = 0
begin
set #emails = #emails + #email + ';'
fetch next from cur into #email
end
close cur
deallocate cur
return #emails
END
You can use table variable instead of temporary table. In that case you can continue to use UDF.
I want to execute a stored procedure in SQL Server and assign the output to a variable (it returns a single value) ?
That depends on the nature of the information you want to return.
If it is a single integer value, you can use the return statement
create proc myproc
as
begin
return 1
end
go
declare #i int
exec #i = myproc
If you have a non integer value, or a number of scalar values, you can use output parameters
create proc myproc
#a int output,
#b varchar(50) output
as
begin
select #a = 1, #b='hello'
end
go
declare #i int, #j varchar(50)
exec myproc #i output, #j output
If you want to return a dataset, you can use insert exec
create proc myproc
as
begin
select name from sysobjects
end
go
declare #t table (name varchar(100))
insert #t (name)
exec myproc
You can even return a cursor but that's just horrid so I shan't give an example :)
You can use the return statement inside a stored procedure to return an integer status code (and only of integer type). By convention a return value of zero is used for success.
If no return is explicitly set, then the stored procedure returns zero.
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerID INT OUTPUT
AS
BEGIN
SELECT #managerID = ManagerID
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
if ##rowcount = 0 -- manager not found?
return 1;
END
And you call it this way:
DECLARE #return_status int;
DECLARE #managerID int;
EXEC #return_status = GetImmediateManager 2, #managerID output;
if #return_status = 1
print N'Immediate manager not found!';
else
print N'ManagerID is ' + #managerID;
go
You should use the return value for status codes only. To return data, you should use output parameters.
If you want to return a dataset, then use an output parameter of type cursor.
more on RETURN statement
Use this code, Working properly
CREATE PROCEDURE [dbo].[sp_delete_item]
#ItemId int = 0
#status bit OUT
AS
Begin
DECLARE #cnt int;
DECLARE #status int =0;
SET NOCOUNT OFF
SELECT #cnt =COUNT(Id) from ItemTransaction where ItemId = #ItemId
if(#cnt = 1)
Begin
return #status;
End
else
Begin
SET #status =1;
return #status;
End
END
Execute SP
DECLARE #statuss bit;
EXECUTE [dbo].[sp_delete_item] 6, #statuss output;
PRINT #statuss;
With the Return statement from the proc, I needed to assign the temp variable and pass it to another stored procedure. The value was getting assigned fine but when passing it as a parameter, it lost the value. I had to create a temp table and set the variable from the table (SQL 2008)
From this:
declare #anID int
exec #anID = dbo.StoredProc_Fetch #ID, #anotherID, #finalID
exec dbo.ADifferentStoredProc #anID (no value here)
To this:
declare #t table(id int)
declare #anID int
insert into #t exec dbo.StoredProc_Fetch #ID, #anotherID, #finalID
set #anID= (select Top 1 * from #t)
I trying to use list of numbers like this.
SELECT *
FROM users
WHERE id in (list_of_ids)
this is part of sql procedure and the variable 'list_of_ids' is varchar and it contains id's like this: 1,2,3,4,5........
How can i use this list and this query
Try this as well. This could be the better solution as it wont require any additional function to create.
oracle regexp_substr will split comma seperated values into different rows and passes to query.
SELECT *
FROM users
WHERE id in
(SELECT regexp_substr(list_of_ids,'[^,]+', 1, level) FROM dual
connect by regexp_substr(list_of_ids, '[^,]+', 1, level) is not NULL)
You can use a ref cursor to construct the sql query, as in this pl/sql block:
declare
list_of_ids varchar2(100) := '1,3,4'; -- example
c_cursor sys_refcursor;
result number;
begin
open c_cursor for ( 'SELECT id '||
'FROM users '||
'WHERE id in ('||list_of_ids||')'
);
fetch c_cursor into result;
while c_cursor%found
loop
dbms_output.put_line('ID='||to_char(result));
fetch c_cursor into result;
end loop;
close c_cursor;
end;
/
Try this solution in your project.
Add a new user function that returns a table.
Code is below:
CREATE FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter
varchar(20) = ' ')
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
And then call it from your stored procedure like below.
DECLARE #list_of_ids AS VARCHAR(100)
SET #list_of_ids = '1,2,3,4,5,6,7,8,9,10,'
SELECT *
FROM users
WHERE id in (SELECT value FROM dbo.fn_Split(#list_of_ids,','))