can anyone please help me right the following stored procedure of split name in first and last name in stored procedure in SQL for update and insert query.
Create[dbo].[storedprocedure]
SELECT LEFT(#FullName, CHARINDEX(',', #FullName) - 1) AS [FirstName],
RIGHT(#FullName, CHARINDEX(',', REVERSE(#FullName)) - 1) AS [LastName]
From table name
Thanks in advance
If I've understood your request you could create a type to use as list parameter for the procedure
CREATE TYPE [dbo].[FullNamesList] AS TABLE(
[FullName] varchar(20) NULL
);
and after this, you can create this procedure to insert splitter name the table you prefer (my FirstLastNameTable)
CREATE PROCEDURE [dbo].[storedprocedure]
#groupFullNames FullNamesList READONLY
AS
BEGIN
INSERT INTO FirstLastNameTable(FirstName, LastName)
SELECT LEFT(G.FullName, CHARINDEX(',', G.FullName) - 1) AS [FirstName],
RIGHT(G.FullName, CHARINDEX(',', REVERSE(G.FullName)) - 1) AS [LastName]
FROM #groupFullNames G
END
Related
I'm inserting DataTable in Database using StoredProcedure but the issue is, its inserting twice the actual number of entries of DataTable to be inserted, the procedure is below, kindly guide me, if I'm using wrong approach, why its duplicating the rows? The return which is required is working fine.
Thanks In Advance
ALTER PROCEDURE [dbo].[proc_InsertStore_Recvry]
(#dt_Recovery Recovery_Store READONLY)
AS
Declare #RecoveryIDs as Table (IDs int, ClientIds int)
declare #StoreID int
declare #ClientID int
declare #Arrears decimal(18, 2)
declare #NetDues decimal(18, 2)
declare #Received decimal(18, 2)
Declare #RecoveryRecID int
begin
select * into #tempTable from #dt_Recovery
declare #Count int
set #Count= (select COUNT(*) from #tempTable)
while(#Count > 0)
begin
set #Count = #Count-1
set #ClientID = (Select top 1 ClientID from #tempTable)
set #StoredID = (Select top 1 StoredID from #tempTable where ClientID=#ClientID)
set #Arrears = (Select top 1 Arrears from #tempTable where ClientID=#ClientID)
set #NetDues = (Select top 1 NDues from #tempTable where ClientID=#ClientID)
set #Received = (Select top 1 Received from #tempTable where ClientID=#ClientID)
Insert into tblRecovery (StoreID, ClientID, Arrears, NetDues, Received)
values (#StoreID,#ClientID,#Arrears,#NetDues,#Received)
select #RecoveryID = Scope_Identity()
insert into #RecoveryIDs (IDs,ClientIds) values (#RecoveryID, #ClientID )
delete from #tempTable where ClientID=#ClientID
end
Select * from #RecoveryIDs
it looks like you are using SQL Server. If yes then why are you using a while-loop to insert values into a table and return the inserted Ids?
The same can be accomplished in a far better way via the OUTPUT clause:
OUTPUT documentation
Example:
INSERT INTO tblRecovery(StoreID, ClientID, Arrears, NetDues, Received) OUTPUT INSERTED.ID, INSERTED.CLientId INTO #RecoveryIDs(IDs, ClientIds) SELECT StoredID, ClientID, Arrears, NDues, Received FROM #tempTable
Aside from that there seems to be no issue with your SQL code. So could you post the .NET code as well?
This question already has answers here:
EF4 - The selected stored procedure returns no columns
(16 answers)
Closed 6 years ago.
I have a stored procedure which generate itself dynamically, in detail I am adding to where, order by clauses dynamically.
Here is my stored procedure:
ALTER PROCEDURE [dbo].[sp_GetConsultants]
#SearchQuery VARCHAR(MAX) = NULL,
#SortDataField VARCHAR(100),
#SortOrder VARCHAR(4),
#PageNum INT,
#PageSize INT,
#sql NVARCHAR(MAX) = NULL OUTPUT
AS
BEGIN
SET #sql = N'
WITH cte AS
(
SELECT
ID, [NO], Firstname, Lastname, ReferanceID,
CAST('''' AS VARCHAR(MAX)) AS ReferanceNO
FROM
dbo.Consultants
WHERE
ReferanceID IS NULL
UNION ALL
SELECT
c.ID, c.[NO], c.Firstname, c.Lastname, c.ReferanceID,
CASE
WHEN ct.ReferanceNO = ''''
THEN CAST(ct.[NO] AS VARCHAR(MAX))
ELSE CAST(ct.[NO] AS VARCHAR(MAX))
END
FROM
dbo.Consultants c
INNER JOIN
cte ct ON ct.ID = c.ReferanceID
)
SELECT *
FROM cte '
+ #SearchQuery
+ ' ORDER BY '
+ #SortDataField + ' ' + #SortOrder
+ ' OFFSET '+ CAST(#PageNum AS VARCHAR(20)) + ' ROW FETCH NEXT ' +CAST(#PageSize AS VARCHAR(20)) + ' ROWS ONLY'
EXEC sp_executesql #sql, N'#SearchQuery VARCHAR(MAX), #SortDataField VARCHAR(100), #SortOrder VARCHAR(4), #PageNum INT, #PageSize INT', #SearchQuery, #SortDataField, #SortOrder, #PageNum, #PageSize
END
I am trying to add this stored procedure to Entity Framework, but without success. Entity Framework can't create a complex type for my stored procedure, I click on the "Get Column Information" button, but the text box below says "The selected stored procedure returns no columns".
Do you know what is the problem?
P.S. It works if I remove parameters from #sql string
Probably because there is no proper SQL Statement in your procedure through which Entity Framework can detect the resulting columns.
A workaround is, to put a SQL Select statement at the end of the procedure which should tell Entity Framework about the result, for example just put following statement at the end of the procedure and update it
SELECT
CAST(1 AS int) AS ID
,CAST(1 AS int) AS [NO]
,N'Fist Name' AS Firstname
,N'Lasat Name' AS Lastname
,CAST(1 AS int) AS ReferanceID
,CAST('' AS VARCHAR(MAX)) AS ReferanceNO
After this, go in Entity Framework and import the procedure, it should show you the columns properly. Once you imported the SP in Entity Framework, go back in Procedure and comment out the last SELECT statement which we just added. This last statement is just for Entity Framework to understand what SP is going to return.
P.S. I don't know exactly the column types, so you should better change the column types in the select statement
Sorry i am not sure how to titled the question well. I want to select few records in sql where a particular column is a set of strings.
Example . I have a table student and has columns ID and name. ID has records 1,2,3,4,5,6 . NAme has A,B,C,D,E,F.
I want to return C,D,E WHERE ID=[3,4,5].
I tried
SELECT FROM student WHERE ID=2,3,4
it gives error, ID=2,3,4 ='2,3,4' and it reads ID as a single columns. I am confused.
Also in my case, ID set are returned in a storedprocedure variable. that is like #ID
SELECT * FROM STUDENT WHERE ID=#ID
#ID above is a variable of a string type holding the set {1,2,3}. Please any help would be appreciated.
Try this:
SELECT * FROM student WHERE ID IN (2,3,4)
Syntax:
test_expression IN
( subquery | expression [ ,...n ]
)
Read more about IN operator here.
WHERE ID=2,3,4 and WHERE ID='2,3,4' are invalid syntax for SQL.
Looks like you can use IN (Transact-SQL) on your situation.
Determines whether a specified value matches any value in a subquery
or a list.
SELECT FROM student WHERE ID IN (2, 3, 4)
Also you might take a look Jeff's question Parameterize an SQL IN clause
If you are passing #ID as a variable with comma separated list of ids, WHERE IN (#ID) will not work.
I think best thing would be to use a Table Valued function to split them first and then query the table. Please check here for a Split() function.
Usage:
SELECT * FROM STUDENT
WHERE ID IN (
SELECT items FROM dbo.Split(#ID, ',') --Split function here
)
If you want to fitler multiple values in Select, you should use "in ()":
SELECT * FROM student WHERE ID in (2,3,4)
OR
SELECT * FROM student WHERE ID between 2 and 4
OR
SELECT * FROM student WHERE ID = 2 OR ID = 3 OR ID = 4
In this case take the first one.
The last one is very slow and not recommended in this scenario.
Please check this out
Select * from Student where Id IN ('2','3','4')
and check this out
Select Username from Student where ID IN ' + '('+ #Id +')'
where #Id=2,3,4
Select * from Student where Id='2'
union all
Select * from Student where Id='3'
union all
Select * from Student where Id='4'
Based on your comment below, you don't want to convert ID to an int. Instead, use LIKE to compare:
SELECT * from STUDENT
WHERE ', '+#ID+', ' LIKE ', '+CAST(ID as NVARCHAR(255)) + ', ';
However, the query will not be indexed. If you want the query to be indexed, then use dynamic SQL:
DECLARE #query NVARCHAR(max) = 'SELECT * FROM STUDENT WHERE ID IN ('+ #ID +')';
EXEC sp_executesql #query;
Since you are using Stored Procedure, that also has only equality compare i.e. id = 1, so either you have too execute three queries by splitting the input by comma separated values.
OR you can add a new procedure with a custom function to server with the SQL
CREATE FUNCTION dbo.myparameter_to_list (#parameter VARCHAR(500)) returns #myOutput TABLE (mytempVal VARCHAR(40))
AS
begin
DECLARE #TempTable table
(
mytempVal VARCHAR(40)
)
DECLARE #MySplittedValue varchar(40), #PositionOfComma int
SET #par = LTRIM(RTRIM(#parameter))+ ','
SET #PositionOfComma = CHARINDEX(',', #parameter, 1)
IF REPLACE(#parameter, ',', '') <> ''
BEGIN
WHILE #PositionOfComma > 0
BEGIN
SET #MySplittedValue = LTRIM(RTRIM(LEFT(#par, #PositionOfComma - 1)))
IF #MySplittedValue <> ''
BEGIN
INSERT INTO #TempTable (mytempVal) VALUES (#MySplittedValue) --Use conversion if needed
END
SET #par = RIGHT(#par, LEN(#par) - #PositionOfComma)
SET #PositionOfComma = CHARINDEX(',', #par, 1)
END
END
INSERT #myOutput
SELECT mytempVal
FROM #TempTable
RETURN
END
In your stored procedure you would use it like this:
Create Procedure StudentSelectFromSet
#Ids VARCHAR(MAX)
AS
SELECT * FROM student Stud
WHERE Stud.Id IN(SELECT value FROM dbo.myparameter_to_list (#Ids))
and then execute this new procedure as you were accessing earlier.
I have a int array of ID's (a lot of checkboxes I can choose from) which I want to get in one database call though a stored procedure.
Is there a way to work with an array of these ID's in SQL Server? I believe it should be something with splitting the array and then loop it (in sql). I just don't know how?
SQL Server 2008
There are many ways to do this:
Pass in a varchar parameter of the values separated by commas and parse that out (not very efficient, but for a small amount of data, not too bad except for the parsing bit)
Pass in XML and use the built in XML functions (SQL Server 2005+ has better support for this than earlier versions)
Use table value parameters (SQL Server 2008+)
Since you are using SQL Server 2008, use table value parameters.
EDIT: Example below
As #Oded mentioned, table valued parameters is the best option.
However, if for some reason you can't use these (perhaps your calling framework's limitations), you can use the following to perform the split to table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[SplitToTable]
(
#List varchar(max), #Delim varchar(1)
)
RETURNS TABLE
AS
RETURN
(
WITH csvtbl(Start, [Stop]) AS (
SELECT Start = convert(bigint, 1), [Stop] =
charindex(#Delim COLLATE Slovenian_BIN2, #list + #Delim)
UNION ALL
SELECT Start = [Stop] + 1, [Stop] = charindex(#Delim
COLLATE Slovenian_BIN2, #list + #Delim, [Stop] + 1)
FROM csvtbl
WHERE ([Stop] > 0)
)
SELECT substring(#list, Start, CASE WHEN [Stop] > 0 THEN [Stop] -
Start ELSE 0 END) AS Value
FROM csvtbl
WHERE ([Stop] > 0)
)
You need to be aware of the default recursion depth of 100. If this isn't enough, increase it by adding the following to your outer calling query:
OPTION (MAXRECURSION 1000) -- or 0 for unlimited
EXAMPLE
SELECT *
FROM MyTable as t
WHERE t.ID IN (
SELECT *
FROM dbo.SplitToTable('1,2,12,34,101', ',')
)
It can be used on joins, etc., too.
I think you need something like...
Declare #query as varchar(500)
Declare #valuesList as varchar(100)
set #valuesList = '1,2,3'
set #query = 'select * From tableName where id in ( ' + #valuesList + ')'
exec(#query)
TO REVERSE THE PROCESS
DECLARE #t TABLE
(
ID int
)
INSERT INTO #t
VALUES (1), (3), (5), (7), (9)
SELECT STUFF(
(
SELECT ',' + CAST(t.ID AS VARCHAR(10))
FROM #t t
FOR XML PATH('')
), 1, 1, '') AS CSV
Courtesy SQLAuthority.
I was wondering how I can pass either an ArrayList, List<int> or StringBuilder comma delimited list to a stored procedure such that I find a list of IDs using IN():
#myList varchar(50)
SELECT *
FROM tbl
WHERE Id IN (#myList)
In C# I am currently building the list as a string which is comma delimeted; however when using nvarchar(50) for example, as the type for the param in the stored procedure - I get an error as it can't convert '1,2,3' to int which it expects between the IN().
Any ideas? Much appreciated.
Pete
You could use a User Defined function such as
CREATE function [dbo].[csl_to_table] ( #list nvarchar(MAX) )
RETURNS #list_table TABLE ([id] INT)
AS
BEGIN
DECLARE #index INT,
#start_index INT,
#id INT
SELECT #index = 1
SELECT #start_index = 1
WHILE #index <= DATALENGTH(#list)
BEGIN
IF SUBSTRING(#list,#index,1) = ','
BEGIN
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
SELECT #start_index = #index + 1
END
SELECT #index = #index + 1
END
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
RETURN
END
Which accepts an nvarchar comma separated list of ids and returns a table of those ids as ints. You can then join on the returned table in your stored procedure like so -
DECLARE #passed_in_ids TABLE (id INT)
INSERT INTO #passed_in_ids (id)
SELECT
id
FROM
[dbo].[csl_to_table] (#your_passed_in_csl)
SELECT *
FROM
myTable
INNER JOIN
#passed_in_ids ids
ON
myTable.id = ids.id
In SQL 2008 there are table-valued-parameters, that make a friendly alternative to parsing CSV; see here for an example.
Otherwise, another option is xml - the xml data type in SQL Server allows you to read this pretty easily (although it takes more transfer bytes).