I need to check if someone is out sick, and unfortunately the data is stored in 2 separate tables. And if they are here, I need to execute path A if they are not here I need to execute path B. This is what I was thinking but it produces compile error after compile error. Can someone provide guidance?
Create Table #Uno (Id Int Identity, employee varchar(50))
Select empName
From employeeDatabase
WHERE empStatus = 'Active'
Declare #outSick bit, #empName varchar(50), #N int, #MAXID int
Set #N = 1
SELECT #MAXID = Max(ID)
FROM #Uno
WHILE (#N<=MAXID)
BEGIN
--Second Table that stores this data
Select #outSick = callIn
FROM callinDatabase
WHERE empName = #empName
--Returns Yes or True
If #outSick = 1
Set #N = #N + 1
Else
--If not out sick Do this sql statement
Set #N = #N + 1
End
Why can't you do this all in one query, like below?
select
employeeDatabase.empName,
case
when callinDatabase.callin = '1' then 'Out Sick'
else 'Not Out Sick'
end as OutSick
from employeeDatabase left join callinDatabase
on employeeDatabase.empName = callinDatabase.empName
where employeeDatabase.empStatus = 'active'
Create Table #Uno (Id Int Identity, employee varchar(50))
Select empName
From employeeDatabase
WHERE empStatus = 'Active'
Declare #outSick bit, #empName varchar(50), #N int, #MAXID int
Set #N = 1
SELECT #MAXID = Max(ID)
FROM #Uno <----- HERE
WHILE (#N<=#MAXID) <------- HERE
BEGIN
--Second Table that stores this data
Select #outSick = callIn
FROM callinDatabase
WHERE empName = #empName
--Returns Yes or True
If #outSick = 1
Set #N = #N + 1
Else
--If not out sick Do this sql statement
Set #N = #N + 1
End <-------------- Here
Related
Requirement: I have a table for storing queries (SQL programs). I need to search and find out in this table such queries which have hardcoded values for a particular column (name) as shown below:
SELECT
*
FROM TABLE1 AC
WHERE
AC.name = 'hardcoded_value1'
UNION
SELECT
*
FROM TABLE2 BC
WHERE BC.name = 'hardcoded_value2'
I have tried and done this using a function and it works fine. But the requirement has a constraint which doesn't allow to make use of any function or stored procedure.
Below is the function definition for reference:-
CREATE OR ALTER FUNCTION [dbo].[GetConstantValue](#QueryID INT)
RETURNS
#Constantvalue TABLE
(
name_ NVARCHAR(2000)
)
AS
BEGIN
Declare #Query NVARCHAR(max) = SELECT code FROM QUERY_TABLE WHERE ID = #QueryID
Declare #StartIndex int = 0,#EndIndex int = 0,#Count int = 0,#ConstStr nvarchar(max) = ''
WHILE #Count <= LEN(#Query)
BEGIN
IF SUBSTRING(#Query,#Count, 1) = CHAR(39)
BEGIN
IF #StartIndex <> 0
BEGIN
SET #ConstStr = #ConstStr + CASE WHEN LEN(#ConstStr)>0 THEN '|' ELSE '' END+ SUBSTRING(#Query,#StartIndex+1,#Count-(#StartIndex+1))
SET #StartIndex = 0
SET #EndIndex = 0
END
ELSE
IF SUBSTRING(#Query,#Count-20, 20) LIKE '%name%[=]%'
SET #StartIndex = #Count
END
SET #Count = #Count + 1
END
INSERT INTO #Constantvalue
SELECT Value FROM string_split(#ConstStr,'|')
RETURN
END
Please suggest me a way to achieve this in the main query itself without making any function calls
I'm trying to do an SQL script here but facing some dificulties as I don't have so much knowledges on that, here is my issue:
I need to create a temp table with pre-determined values (dbrsm01 to dbrsm30) and check iterating through these values if one of them is available on MSSQL server to be used as a new database, if one of these values is already in use it needs to be ignored as I need to create a new DB using this value.
Here is what I've done so far:
DECLARE #temp TABLE (id int, dbname varchar(10))
INSERT INTO #temp VALUES(1,'dbrsm01');
INSERT INTO #temp VALUES(2,'dbrsm02');
INSERT INTO #temp VALUES(3,'dbrsm03');
...
INSERT INTO #temp VALUES(27,'dbrsm27');
INSERT INTO #temp VALUES(28,'dbrsm28');
INSERT INTO #temp VALUES(29,'dbrsm29');
INSERT INTO #temp VALUES(30,'dbrsm30');
DECLARE #maxid INT, #counter INT, #tempname VARCHAR(10), #nameset VARCHAR(10)
SET #counter = 1
SELECT #maxid = COUNT(*) FROM #temp
WHILE (#counter <= #maxid OR #nameset = #tempname)
BEGIN
SET #tempname = (SELECT dbname FROM #temp WHERE id = #counter)
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = #tempname)
BEGIN
SET #nameset = #tempname
END
SET #counter = #counter + 1
END
SELECT #nameset as [#dbname]
Any help on that is appreciate! Thank you all!
This doesn't need to be iterative at all. You can do this in a single statement:
WITH Tally AS (
SELECT 1 AS i
UNION ALL
SELECT i + 1
FROM Tally
WHERE i + 1 <= 30)
SELECT 'dbrsm' + CONVERT(varchar(7),T.i)
FROM Tally T
LEFT JOIN sys.databases d ON 'dbrsm' + CONVERT(varchar(7),T.i) = d.[name]
WHERE d.database_id IS NULL;
Edit: A mindset you need to change when writing SQL is thinking programmatically. You don't want to think about what you're going to do to a row, you need to think about what you're going to do to a column. Using loops are not a way of thinking in a dataset approach (normally).
Edit: Nevermind, here's how to make a CREATE statement and make all the databases:
DECLARE #SQL nvarchar(MAX);
WITH Tally AS (
SELECT 1 AS i
UNION ALL
SELECT i + 1
FROM Tally
WHERE i + 1 <= 30)
SELECT #SQL = STUFF((SELECT NCHAR(10) + N'CREATE DATABASE ' + QUOTENAME(N'dbrsm' + CONVERT(varchar(7),T.i)) + N';'
FROM Tally T
LEFT JOIN sys.databases d ON 'dbrsm' + CONVERT(varchar(7),T.i) = d.[name]
WHERE d.database_id IS NULL
FOR XML PATH ('')),1,1,'');
PRINT #SQL; --This is your best friend for troubleshooting
--EXEC sp_executesql #SQL; --Uncomment to run your dynamic SQL
You could use dynamic SQL:
DECLARE #sql NVARCHAR(MAX)
,#maxid INT = (SELECT COUNT(*) FROM #temp)
,#counter INT = 1
,#tempname VARCHAR(10)
,#nameset VARCHAR(10);
WHILE (#counter <= #maxid)
BEGIN
SET #tempname = (SELECT dbname FROM #temp WHERE id = #counter);
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = #tempname)
BEGIN
SET #nameset = #tempname;
SET #sql = 'CREATE DATABASE ' + QUOTENAME(#nameset);
PRINT #sql;
EXEC (#sql);
END
SET #counter += 1;
END
You can use BREAK and do what you want, like this:
DECLARE #temp TABLE (id int, dbname varchar(10))
INSERT INTO #temp VALUES(1,'dbrsm01');
INSERT INTO #temp VALUES(2,'dbrsm02');
INSERT INTO #temp VALUES(3,'dbrsm03');
DECLARE #maxid INT, #counter INT, #tempname VARCHAR(10), #nameset VARCHAR(10)
SET #counter = 1
SELECT #maxid = COUNT(*) FROM #temp
WHILE (#counter <= #maxid /*OR #nameset = #tempname --YOU DON'T NEED THIS */)
BEGIN
SELECT #tempname = dbname FROM #temp WHERE id = #counter
PRINT #tempname
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = #tempname)
BEGIN
SET #nameset = #tempname
PRINT 'ITS FREE'
BREAK
END
ELSE
PRINT 'ITS IN USE!'
SET #counter = #counter + 1
END
SELECT #nameset as [#dbname]
If you need to create all DB's that dont exist, remove the BREAK and add your logic (CREATE DATABASE ...)
SELECT 'CREATE Database '+A.dbname+'
GO '
FROM
(
SELECT K.dbname
FROM #temp K
LEFT JOIN sys.databases Y
ON K.dbName = Y.Name
WHERE Y.name is NULL
)A
You can copy the result of this statement and run it.
I am trying to populate the AspNetUsers table using a stored procedure, but I get the following error:
Msg 515, Level 16, State 2, Procedure Insert_Users, Line 36 Cannot
insert the value NULL into column 'Id', table
'MyDatabase.dbo.AspNetUsers'; column does not allow nulls. INSERT
fails.
I read on some other posts that there should be the following attribute on the column Id: [DatabaseGenerated(DatabaseGeneratedOption.Identity)], but I cannot manage to find where is physically declared.
I don't want to insert all users manually because I'm out of time and I need to do it as quick as possible.
BEGIN
SET NOCOUNT ON;
DECLARE #id uniqueidentifier
DECLARE #email nvarchar(256)
DECLARE #emailconfirmed bit
SET #emailconfirmed = 0
DECLARE #twofactorenabled bit
SET #twofactorenabled = 0
DECLARE #lockoutenabled bit
SET #lockoutenabled = 1
DECLARE #accessFailed bit
SET #accessFailed = 1
DECLARE #username nvarchar(256)
DECLARE #fname nvarchar(50)
DECLARE #lname nvarchar(50)
DECLARE #athleteKey int
SET #athleteKey = 41809
DECLARE #atheletsCount int
SET #atheletsCount = 0;
SET #atheletsCount = (SELECT COUNT(*) FROM [BIBD].[dbo].[Athlete])
WHILE #athleteKey < #atheletsCount
SET #id = NEWID() --Line 36
print CAST(#id AS nvarchar(128))
SET #fname = (SELECT FirstName FROM [BIBD].[dbo].[Athlete] where AthleteKey=#athleteKey)
SET #lname = (SELECT LastName FROM [BIBD].[dbo].[Athlete] where AthleteKey=#athleteKey)
SET #username = CONCAT(LOWER(#fname),'.',LOWER(#lname))
SET #email = CONCAT(LOWER(#fname), '.', LOWER(#lname), '#gmail.com')
INSERT INTO [MyDatabase].[dbo].[AspNetUsers]
(Id
,Email
,EmailConfirmed
,[TwoFactorEnabled]
,LockoutEnabled
,AccessFailedCount
,UserName
,FirstName
,LastName)
VALUES
(CAST(#id AS nvarchar(128))
,#email
,#emailconfirmed
,#twofactorenabled
,#lockoutenabled
,#accessFailed
,#username
,#fname
,#lname)
IF #athleteKey % 5 = 0
INSERT INTO [MyDatabase].[dbo].[AspNetUserRoles]
(UserId,RoleId) VALUES (#id, 3)
ELSE
INSERT INTO [MyDatabase].[dbo].[AspNetUserRoles]
(UserId,RoleId) VALUES (#id, 4)
SET #athleteKey = #athleteKey+1
END
You need BEGIN-END in your WHILE loop.
Otherwise it just do not assign value to #id and does not process the loop
I have trigger on insert like that :
ALTER TRIGGER [dbo].[trTblNameSetRefNo]
ON [dbo].[TblName]
AFTER INSERT
AS BEGIN
UPDATE TblName
SET RefNumber = dbo.GetNextRefNo(i.SomeField)
FROM TblName
INNER JOIN inserted i on i.ID = TblName.ID
END
But it doesn't work. When I 'hardcode' field RefNumber , for example : SET RefNumber = 'test', it works correctly.
Also when I call function outside of the trigger, it return proper result.
And this is my function that must return value in trigger :
ALTER FUNCTION [dbo].[GetNextRefNo]
(#ValueField INT)
RETURNS NVARCHAR(250)
AS
BEGIN
DECLARE #lastId INT;
DECLARE #result NVARCHAR(25);
DECLARE #CurrentIdentifier NVARCHAR(25);
SELECT TOP 1
#lastId = CAST(Substring(RefNumber, Charindex('-', RefNumber) + 4, Len(RefNumber )) AS INT) + 1
FROM
TblName
ORDER BY
ID DESC
IF ##ROWCOUNT < 1 --if empty table , set start number
BEGIN
SET #lastId = 1000
END
SELECT #CurrentIdentifier = 'SIT'
SET #result = #CurrentIdentifier + '-' + Substring ( Cast(Year(Getdate()) AS NVARCHAR), 3, 2) + '-' + Cast(#lastId AS NVARCHAR)
RETURN #result
END
Any ideas what I'm doing wrong?
Your function returns what is probably an incorrect result when RefNumber = '' and it returns NULL when RefNumber = NULL, as would happen for a newly inserted record.
The design of the above code is beyond bad.
Suggested approach:
Use ID field as the counter and generate RefNumber based on that, while concatating Year as needed.
Example function:
ALTER FUNCTION [dbo].[GetNextRefNo] (#ID INT)
returns NVARCHAR(250)
AS
BEGIN
DECLARE #lastId INT;
DECLARE #result NVARCHAR(25);
DECLARE #CurrentIdentifier NVARCHAR(25);
SELECT #CurrentIdentifier = 'SIT'
SET #ID = #ID + 1000
SET #result = #CurrentIdentifier + '-' + Substring ( Cast(Year(Getdate()) AS NVARCHAR), 3, 2) + '-' + Cast(#ID AS NVARCHAR)
RETURN #result
END
Example Trigger:
ALTER TRIGGER [dbo].[trTblNameSetRefNo] ON [dbo].[TblName]
AFTER INSERT AS BEGIN
UPDATE TblName
SET RefNumber = dbo.GetNextRefNo(i.ID)
FROM TblName
INNER JOIN inserted i on i.ID = TblName.ID
END
Alternatively create another table to hold the current RefNumber seed.
I have a stored procedure like this:
ALTER procedure [dbo].[delivary1]
#dedate nvarchar(100),
#carid nvarchar(100)
AS
BEGIN
declare #transid int
declare #status int
declare #count int,
#currentdate nvarchar(50)
select #currentdate = GETDATE()
SET NOCOUNT ON;
select #count = count(*)
from Transaction_tbl
where TBarcode = #carid
if #count=0
begin
return -1
end
else
begin
select #status = t1.Status
from Transaction_tbl t1
where t1.TBarcode = #carid
if #status = 4
begin
select #transid = t.transactID
from Transaction_tbl t
where t.TBarcode = #carid
update Transaction_tbl
set DelDate = '' + #currentdate + '', Status=5
where TBarcode = #carid
update KHanger_tbl
set Delivered = 1
where transactid = #transid
return 4
end
if #status = 5
begin
return 5
end
if #status=0
begin
return 0
end
if #status=1
begin
return 1
end
if #status = 2
begin
return 2
end
if #status = 3
begin
return 3
end
end
end
My database has more than 10 lack of records. Sometimes this takes a long time to execute..
Is there any way to write this stored procedure any simpler than this way?
Any help is very much appreciated.
Thanks in advance
Execution plan of my stored procedure
Well, lets get serious.
Your end of the SP is redundant, jsut return #status.
The update is badly programming in using string for the date, but that is not relevant forspeed.
The speed is just in the Select. Interesting enough you miss an index which is shown in the screenshot you sent - which tells me you never bothered to even look at it before posting.
Please start considering indices and planning them. In your case you defintiely miss an index.
You do not need to return the value for status, it just doent make any sense,
also add the missing index which suggests you will get around 93% improvement in your performance.
you can write this procedure with an OUTPUT parameter something like this...
ALTER procedure [dbo].[delivary1]
#dedate nvarchar(100),
#carid nvarchar(100),
#status INT OUTPUT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #transid int, #count int,#currentdate nvarchar(50)
SET #currentdate = GETDATE();
select #count = count(*) from Transaction_tbl where TBarcode = #carid
if (#count = 0)
begin
SET #status = -1;
end
else
begin
select #status = t1.[Status] from Transaction_tbl t1 where t1.TBarcode = #carid
if (#status = 4)
begin
select #transid = t.transactID
from Transaction_tbl t
where t.TBarcode = #carid
update Transaction_tbl
set DelDate = '' + #currentdate + ''
, [Status] = 5
where TBarcode = #carid
update KHanger_tbl
set Delivered=1
where transactid = #transid
end
end
END
How to add Missing Index
Go to your execution plan Right Click where it is showing Missing Index, and the click on the Missing Index Details
And it will Give you the Index Definition in a new query window that SQL Server thinks will help it to improve the performance of this query. All you need to do now is Just execute the Statement and it will create the index for you.
Index Definition
/*
Missing Index Details from SQLQuery1.sql - ALI-PC.AdventureWorks2008R2 (My Server\UserName (59))
The Query Processor estimates that implementing the following index could improve the query cost by 95.7414%.
*/
/*
USE [AdventureWorks2008R2]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [Sales].[SalesOrderHeader] ([TerritoryID],[ShipMethodID],[SubTotal],[Freight])
INCLUDE ([SalesOrderNumber],[CustomerID])
GO
*/