how to convert the stored procedure to Linq - sql

this is my Stored Procedure how to write in Linq
please help me
ALTER PROCEDURE sample
(#LID var char(20)=null
)
As
SET NO COUNT ON;
begin
declare #err1 int
begin transaction
BEGIN
Select * from sample_table where Aid is not null and Sid is not null and #LID IS NULL OR Lid = #LID
order by SrNo1, SrNo2, SrNo3
END

you need this:
var query = dbContext.DraftLOB
.Where(u => u.AssemblyId.HasValue &&
u.SessionId.HasValue &&
#LOBID == null ? true : u.LOBId == #LOBID)
.OrderBy(u => u.SrNo1)
.ThenBy(u => u.SrNo2)
.ThenBy(u => u.SrNo3)
.ToList();

Related

Optional parameters in cursor where clause

I have the following sample query which takes values from procedure parameters. The parameter can be either passed or default to null.
SELECT * FROM table
WHERE( table_term_code = '201931'
OR (table_term_code = '201931' and table_DETL_CODE ='CA02')
OR ( table_term_code = '201931' and table_ACTIVITY_DATE = sysdate)
OR ( table_term_code = '201931' and table_SEQNO = NULL));
i.e the user can input term code and not input any other parameter, or can input term code and table_DETL_CODE and not any other input parameter.
Same goes for the other 2 or conditions.
If a term code is passed and table_DETL_CODE is null, the query should return all the values for that term_code, whereas this query returns null.
Is there a way to achieve this without case or if conditions in PL/SQL?
If I understood you correctly, this might be what you're looking for:
select *
from your_table
where (table_term_code = :par_term_code or :par_term_code is null)
and (table_detl_code = :par_detl_code or :par_detl_code is null)
and (table_activity_date = :par_activity_date or :par_activity_date is null)
and (table_seqno = :par_seqno or :par_seqno is null)
The description seems to that you require user to enter table_term_code and then either none or exactly 1 of the other 3. If so then perhaps:
select *
from your_table
where table_term_code = :par_term_code
and ( (table_detl_code = :par_detl_code and :par_activity_date is null and :par_seqno is null)
or (table_activity_date = :par_activity_date and :par_detl_code is null and :par_seqno is null)
or (table_seqno = :par_seqno and :par_detl_code is null and :par_activity_date is null)
or (table_seqno is null and :par_detl_code is null and :par_activity_date is null)
);

Cannot find ID , but really exists in Postgres

I am trying to pull data from a database to create a progress board fro some this query keeps returning for output."Data", even for values of projectId that actually exist in DB, project_id is an id that is inputted into the function.
-- FUNCTION: "ProjectProgress"."GetStepStatusbyProject"("Common"."InputDBMessage")
-- DROP FUNCTION "ProjectProgress"."GetStepStatusbyProject"("Common"."InputDBMessage");
CREATE OR REPLACE FUNCTION "ProjectProgress"."GetStepStatusbyProject"(
userinput "Common"."InputDBMessage")
RETURNS "Common"."OutputDBMessage"
LANGUAGE "plpgsql"
COST 100
VOLATILE
AS $BODY$
-- History:
-- 04/24/2020 Nick: Created Function
DECLARE
status_info jsonb;
input_params jsonb;
project_id bigint;
project_exists bool = true;
output "Common"."OutputDBMessage";
BEGIN
input_params := userinput."Parameters";
project_id := input_params ->> 'Id';
PERFORM "Log"."LogBeginRoutine"(userinput."UserName", userinput."ApplicationName", 'StepStatuses', 'GetStepStatusbyProject', userinput."ClientId", userinput."SessionId");
SELECT INTO project_exists (EXISTS(SELECT * FROM "LIMS"."Projects" WHERE "Id" = project_id));
IF NOT project_exists THEN
output."ErrorCode" = 1;
output."UserMessage" = 'project_id id not found';
ELSE
SELECT
array_to_json(array_agg(( ss.*, st."Color",st."Description",st."Icon"))) INTO status_info
FROM "LIMS"."Projects" as pr INNER JOIN "ProjectProgress"."Steps" as s
ON s."ProjectId" = pr."Id"
INNER JOIN (
SELECT
stepstatus.*
FROM
"ProjectProgress"."StepStatuses" AS stepstatus INNER JOIN
(
SELECT
MAX("Id") m_id, "StepId"
FROM
"ProjectProgress"."StepStatuses"
GROUP BY "StepId"
) AS mss ON mss.m_id = stepstatus."Id"
) as ss
ON ss."StepId" = s."Id"
INNER JOIN "ProjectProgress"."StatusTemplates" as st
ON ss."StatusTemplateId" = st."Id"
WHERE
st."Description" != 'Not Started' AND pr."Id" = project_id;
output."Data" := status_info;
output."ErrorCode" := 0;
output."UserMessage" := 'status successfully retrieved.';
PERFORM "Log"."LogEndSuccessRoutine"(userinput."UserName", userinput."ApplicationName", 'StepStatuses', 'GetStepStatusbyProject', userinput."ClientId", userinput."SessionId");
return output;
END
$BODY$;

How to store the result of multiple SELECT statements in a stored procedure

I have a stored procedure where I need to run three separate SELECT statements and store the result in a variable.
I tried something like this:
SELECT #tier1MenuIds = Id
FROM TheGateKeeper.NavigationTier1
WHERE ([Page Name] = #currentSlug)
SELECT #tier2MenuIds = Id
FROM TheGateKeeper.NavigationTier2
WHERE ([Page Name] = #currentSlug)
SELECT #tier3MenuIds = Id
FROM TheGateKeeper.NavigationTier3
WHERE ([Page Name] = #currentSlug)
But it gives me an error saying
Incorrect syntax near '('.
The statement works if I remove the bottom two SELECTs. Any other options?
Edit: I am using SQL Server. Here is the full code:
CREATE PROCEDURE [TheGateKeeper].[editContent]
#description nvarchar(300),
#content nvarchar(MAX),
#title nvarchar(50),
#dateModified date,
#headerImageName nvarchar(100),
#slug nvarchar(50),
#id int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #currentSlug as nvarchar(100);
DECLARE #tier1MenuIds as int;
DECLARE #tier2MenuIds as int;
DECLARE #tier3MenuIds as int;
/* Check if the post exists */
SELECT #currentSlug = Slug
FROM TheGateKeeper.Posts
WHERE (Id = #id)
IF (##ROWCOUNT = 1)
BEGIN
/* Temporarily unlink all menu items linking to post */
SELECT #tier1MenuIds = Id
FROM TheGateKeeper.NavigationTier1
WHERE ([Page Name] = #currentSlug)
SELECT #tier2MenuIds = Id
FROM TheGateKeeper.NavigationTier2
WHERE ([Page Name] = #currentSlug)
SELECT #tier3MenuIds = Id
FROM TheGateKeeper.NavigationTier3
WHERE ([Page Name] = #currentSlug)
/* Update the post in the database */
UPDATE Posts
SET (Description = #description, [Content] = #content, Title = #title, [Date Modified] =#dateModified, HeaderImageName = #headerImageName, slug =#slug)
WHERE id = #id
RETURN 1
END
ELSE
BEGIN
RETURN 0
END
Remove the parentheses from your UPDATE statement; they are unnecessary.
Your update statement should be:
UPDATE Posts
SET Description = #description, [Content] = #content, Title = #title,
[Date Modified] =#dateModified, HeaderImageName = #headerImageName,
slug =#slug
WHERE id = #id

Multiple 'in' statements in a where clause that need to match against each other

I have a very long query that is essentially an extension of the following:
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where (suite_id = 'CCBG08' and lease_id = '205059')
or (suite_id = 'CCBG14' and lease_id = '152424')
or (suite_id = 'CCCF048' and lease_id = '150659')
The where clause for this will have ~40 rows when complete. In order to make this task easier I was hoping to do something similar to the following:
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where suite_id in('CCBG08', 'CCBG14', 'CCCF048')
and lease_id in('205059', '152424', '150659')
Unfortunately lease_id isn't a unique field and there can be multiple lease_id's to the same suite_id (so subsequently the second query is unusable).
Is there a better way to do the first update statement given that this solution won't work?
You may create table type and pass the values thru it, like that:
CREATE TYPE Suite_Lease AS TABLE
(
suite_id varchar(15) NOT NULL,
lease_id varchar(15) NOT NULL
)
GO
CREATE PROC DoUpdate
#Params Suite_Lease READONLY,
#uplift varchar(15),
#code varchar(15)
AS
update property.lease_period set
scca_uplift = #uplift,
scca_notes_code = #code
from property.lease_period tab
JOIN #params filt
on tab.suite_id=filt.suite_id AND tab.lease_id=filt.lease_id
This will keep your Procedure cache dry and clean, instead if you using multiple "big" where clauses
How to pass table parameter into stored procedure (c#):
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("suite_id", typeof (string)) {AllowDBNull = false, MaxLength = 15});
dt.Columns.Add(new DataColumn("lease_id", typeof (string)) {AllowDBNull = false, MaxLength = 15});
dt.Rows.Add("CCBG08", "205059");
... add more rows for match
using (var c = new SqlConnection("ConnectionString"))
{
c.Open();
using(var sc = c.CreateCommand())
{
sc.CommandText = "DoUpdate";
sc.CommandType = CommandType.StoredProcedure;
sc.Parameters.AddWithValue("#uplift", "110");
sc.Parameters.AddWithValue("#code", "21006");
sc.Parameters.Add(new SqlParameter("#Params", SqlDbType.Structured) { TypeName = null, Value = dt });
sc.ExecuteNonQuery();
}
}
Using the trick from this article. This looks a bit ugly, but it does the trick:
update property.lease_period
set scca_uplift = #uplift, scca_notes_code = #code
from property.lease_period tab
JOIN (
select 'CCBG08' as suite_id, '205059' as lease_id union all
select 'CCBG14', '152424' union all
select 'CCCF048', '150659'
) xxx
on tab.suite_id=xxx.suite_id AND tab.lease_id=xxx.lease_id
Try this
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where (suite_id in,lease_id) in
(select suite_id in,lease_id from XXX_table where CONDITION)
The last SELECT should give you those 40 combinations.
Derived from a comment by #dasblinkenlight (for Oracle) another possible way to do this would be the following:
select *
from property.lease_period
where (suite_id + ' ' + lease_id)
in (
('CCBG08 205059'),
('CCBG14 152424'),
('CCCF048 150659')
)
This isn't very recommended as it would be bad for indexing (concatenation on MicrosoftSQL) however I thought it was interesting all the same.
dasblinkenlights original comment:
#Michael I wish you were asking about Oracle, it's a lot cleaner
there: you do where (lease_period,lease_id) in
(('CCBG08','205059'),('CCBG14','152424'),('CCCF048','150659')), and it
does the trick. Why SQL Server couldn't do it is beyond me. –

How to get a distinct list of words used in all Field Records using MS SQL?

If I have a table field named 'description', what would be the SQL (using MS SQL) to get a list of records of all distinct words used in this field.
For example:
If the table contains the following for the 'description' field:
Record1 "The dog jumped over the fence."
Record2 "The giant tripped on the fence."
...
The SQL record output would be:
"The","giant","dog","jumped","tripped","on","over","fence"
I do not think you can do this with a SELECT. The best chance is to write a user defined function that returns a table with all the words and then do SELECT DISTINCT on it.
Disclaimer: Function dbo.Split is from http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648
CREATE TABLE test
(
id int identity(1, 1) not null,
description varchar(50) not null
)
INSERT INTO test VALUES('The dog jumped over the fence')
INSERT INTO test VALUES('The giant tripped on the fence')
CREATE FUNCTION dbo.Split
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
CREATE FUNCTION dbo.SplitAll(#SplitOn nvarchar(5))
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
DECLARE My_Cursor CURSOR FOR SELECT Description FROM dbo.test
DECLARE #description varchar(50)
OPEN My_Cursor
FETCH NEXT FROM My_Cursor INTO #description
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #RtnValue
SELECT Data FROM dbo.Split(#description, #SplitOn)
FETCH NEXT FROM My_Cursor INTO #description
END
CLOSE My_Cursor
DEALLOCATE My_Cursor
RETURN
END
SELECT DISTINCT Data FROM dbo.SplitAll(N' ')
I just had a similar problem and tried using SQL CLR to solve it. Might be handy to someone
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Collections.Generic;
public partial class UserDefinedFunctions
{
private class SplitStrings : IEnumerable
{
private List<string> splits;
public SplitStrings(string toSplit, string splitOn)
{
splits = new List<string>();
// nothing, return empty list
if (string.IsNullOrEmpty(toSplit))
{
return;
}
// return one word
if (string.IsNullOrEmpty(splitOn))
{
splits.Add(toSplit);
return;
}
splits.AddRange(
toSplit.Split(new string[] { splitOn }, StringSplitOptions.RemoveEmptyEntries)
);
}
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return splits.GetEnumerator();
}
#endregion
}
[Microsoft.SqlServer.Server.SqlFunction(FillRowMethodName = "readRow", TableDefinition = "word nvarchar(255)")]
public static IEnumerable fnc_clr_split_string(string toSplit, string splitOn)
{
return new SplitStrings(toSplit, splitOn);
}
public static void readRow(object inWord, out SqlString word)
{
string w = (string)inWord;
if (string.IsNullOrEmpty(w))
{
word = string.Empty;
return;
}
if (w.Length > 255)
{
w = w.Substring(0, 254);
}
word = w;
}
};
It is not the fastest approach but might be used by somebody for a small amount of data:
declare #tmp table(descr varchar(400))
insert into #tmp
select 'The dog jumped over the fence.'
union select 'The giant tripped on the fence.'
/* the actual doing starts here */
update #tmp
set descr = replace(descr, '.', '') --get rid of dots in the ends of sentences.
declare #xml xml
set #xml = '<c>' + replace(
(select ' ' + descr
from #tmp
for xml path('')
), ' ', '</c><c>') + '</c>'
;with
allWords as (
select section.Cols.value('.', 'varchar(250)') words
from #xml.nodes('/c') section(Cols)
)
select words
from allWords
where ltrim(rtrim(words)) <> ''
group by words
In SQL on it's own it would probably need to be a big stored procedure, but if you read all the records out to the scripting language of your choice, you can easily loop over them and split each out into arrays/hashes.
it'd be a messy stored procedure with a temp table and a SELECT DISTINCT at the end.
if you had the words already as records, you would use SELECT DISTINCT [WordsField] from [owner].[tablename]