Increment read count giving incorrect output - tsql

Hi I have stored procedure with Merge statements using the cursor to count Read, Insert, update and delete with an increment read count
CREATE PROCEDURE StagingProcedure
AS
BEGIN
DECLARE #output TABLE(change VARCHAR(20));
DECLARE #Reads INT,
#Inserts INT =0,
#Updates INT=0,
#Deletes INT=0;
DECLARE #Cursor_Month NVARCHAR(10)
DECLARE CUR_MONTHS CURSOR FAST_FORWARD FOR
SELECT DISTINCT year_month_submission
FROM StagingFile
WHERE Type = 'Payment' AND [status] IN('New','Updated')
ORDER BY year_month_submission ASC
OPEN CUR_MONTHS
FETCH NEXT FROM CUR_MONTHS INTO #Cursor_Month
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT THE MAIN MERGE CODE HERE, this example
**SELECT #Reads = #reads + COUNT(*)**
FROM StagingFile bf
INNER JOIN StagingData bd
ON bf.FileID = bd.FileID
WHERE bf.Type = 'Claim' and bf.[status] IN('New','Updated') and bf.year_month_submission = #Cursor_Month
DECLARE #FilesList TABLE(fileuid UNIQUEIDENTIFIER)
INSERT INTO #FilesList (fileid) (SELECT DISTINCT FileID FROM StagingFile
WHERE [status] IN('New','Updated') and Type = 'Payment' and year_month_submission = #Cursor_BDXMonth)
MERGE INTO Table a WITH (HOLD LOCK) AS tgt
USING (
SELECT Distinct
JSON_VALUE(DocumentJSON, '$.EntityID') AS EntityID,
CASE JSON_VALUE(DocumentJSON, '$.Denial')
WHEN 'Yes' THEN 'Y'
WHEN 'No' THEN 'N'
ELSE JSON_VALUE(DocumentJSON, '$.Denial')
END AS Denial
FROM Table1 bd
INNER JOIN table2 bf ON bf.FileID = bd.FileID
WHERE bf.Type = 'Payment'
) AS src ON tgt.[ID] = src.[ID]
WHEN MATCHED
)) THEN
UPDATE SET tgt.ID = src.ID,
tgt.EntityID = src.EntityID,
tgt.Denial = src.Denial,
WHEN NOT MATCHED BY THE TARGET
THEN INSERT (ID, EntityID, Denial)
VALUES (src. ID, src.EntityID, src. Denial)
WHEN NOT MATCHED BY THE SOURCE
AND tgt.FileID IN(SELECT fileid FROM #FilesList)
THEN update
Set tgt.Isdeleted=1,
tgt.lastupdated=getdate()
THEN DELETE
OUTPUT $action INTO #output;
SELECT #Inserts = #Inserts + count(*) FROM #output WHERE change = 'INSERT'
SELECT #Updates = #Updates + count(*) FROM #output WHERE change = 'Update'
SELECT #Deletes = #Deletes + count(*) FROM #output WHERE change ='Delete'
FETCH NEXT FROM CUR_MONTHS INTO #Cursor_BDXMonth
END
SELECT #Reads ReadCount, #Inserts InsertCount, #Updates UpdateCount, #Deletes DeleteCount;
CLOSE CUR_MONTHS
DEALLOCATE CUR_MONTHS
END;
The output of StoredProcedure not syncing with the insert statement, Please could advise what this script exactly doing is there an issue in the Cursor statement under Read count not sure if this is something to incremental read count. I don't have 45 updated records seems like somewhere it's counting wrongly.
ReadCount
InsertCount
UpdateCount
DeleteCount
38
21
45
13
---------
-----------
-----------
-----------

Related

TSQL: Multiple IF conditions in a stored procedure

Hope I can get suggestions.
I created a stored procedure, but it is not working as intended. Basically if a value exists in a table then it will just select it, else it will insert rows to that table.
TABLE_A -- This is where I need to check if the code exists
CODE
LETTER
GREEEN
A
YELLOW
B
TABLE_B -- I use this table to get letters, there are only 2 groups.
GROUP
LETTERS
1
A
1
B
2
C
This is the stored procedure I made
CREATE PROCEDURE GET_CODE
DECLARE
#CODE VARCHAR(5) = 'RED'
,#GROUP INT = '1'
AS
BEGIN
DECLARE
#GROUPID dbo.UniqueID
,#COUNT = (SELECT count(Code) from TABLE_A where [Code] = #CODE)
/** Get letters **/
IF #GROUP = '1'
begin
insert into #GROUPID
select LETTERS from TABLE B
where GROUP = #GROUP
end
else IF #GROUP = '2'
begin
insert into #GROUPID
select LETTERS from TABLE B
where GROUP = #GROUP
end
/** if not exists insert, else go to next step **/
IF #COUNT = 0
begin
insert into TABLE_A VALUES
select
#CODE
,LETTERS
FROM #GROUPid
end
/** select where #code **/
SELECT * FROM TABLE_A where CODE = #CODE
END
Works well if the code exist, but if the code does not exist, it does not insert to TABLE_A
You're sproc is never going to insert into TABLE_A because you did not tell it to. You are inserting into the variable #GROUPID.
This will create a temporary table (note the #) and populate it with a row
DROP TABLE IF EXISTS #table_a
CREATE TABLE #table_a (code NVARCHAR(10), groupID INT)
INSERT INTO #table_a (code, groupID) VALUES
('Green', 2)
SELECT *
FROM #table_a
code groupID
---------------
Green 2
If we then do what you're attempting (outside of a stored procedure for now):
DECLARE #code NVARCHAR(10) = 'Red', #groupID INT = 1
IF NOT EXISTS (SELECT 1 FROM #table_a WHERE #code = code AND groupID = #groupID)
BEGIN
INSERT INTO #table_a (code, groupID) VALUES
(#code, #groupID)
END
SELECT *
FROM #table_a
WHERE code = #code
AND groupID = #groupID
code groupID
---------------
Red 1
First we declare some variables, and give them values.
Then we look to see if the values exist in the table using NOT EXISTS.
If that returns true we INSERT those values into #table_a.
Since we now know that they will exist (they either did already, or we just inserted them) we can then just select those values.
If we do the same thing again, but this time with existing values we can see it doesn't insert them again:
SET #code = 'Red'
SET #groupID = 1
IF NOT EXISTS (SELECT 1 FROM #table_a WHERE #code = code AND groupID = #groupID)
BEGIN
INSERT INTO #table_a (code, groupID) VALUES
(#code, #groupID)
END
SELECT *
FROM #table_a
WHERE code = #code
AND groupID = #groupID
code groupID
Red 1

Issue with PK violation on insert

I have a scenario where almost all of the tables have issues with the PK value as follows. This results is a database error or the violation of the PK insert.
When using the DBCC CheckIdent it displays an inconsistency between the next value and the current one.
Can anyone have a reason for the mismatch happening on several tables?
Since this database is then replicate, I'm afraid this error will propagate across the environment.
I adapted this script to fix it, but really trying to figure out the root of the problem.
/** Version 3.0 **/
if object_id('tempdb..#temp') is not null
drop table #temp
;
with cte as (
SELECT
distinct
A.TABLE_CATALOG AS CATALOG,
A.TABLE_SCHEMA AS "SCHEMA",
A.TABLE_NAME AS "TABLE",
B.COLUMN_NAME AS "COLUMN",
IDENT_SEED (A.TABLE_NAME) AS Seed,
IDENT_INCR (A.TABLE_NAME) AS Increment,
IDENT_CURRENT (A.TABLE_NAME) AS Curr_Value
, DBPS.row_count AS NumberOfRows
FROM INFORMATION_SCHEMA.TABLES A
inner join INFORMATION_SCHEMA.COLUMNS B on b.TABLE_NAME = a.TABLE_NAME and b.TABLE_SCHEMA = a.TABLE_SCHEMA
inner join sys.identity_columns IC on OBJECT_NAME (IC.object_id) = a.TABLE_NAME
inner join sys.dm_db_partition_stats DBPS ON DBPS.object_id =IC.object_id
inner join sys.indexes as IDX ON DBPS.index_id =IDX.index_id
WHERE A.TABLE_CATALOG = B.TABLE_CATALOG AND
A.TABLE_SCHEMA = B.TABLE_SCHEMA AND
A.TABLE_NAME = B.TABLE_NAME AND
COLUMNPROPERTY (OBJECT_ID (B.TABLE_NAME), B.COLUMN_NAME, 'IsIdentity') = 1 AND
OBJECTPROPERTY (OBJECT_ID (A.TABLE_NAME), 'TableHasIdentity') = 1 AND
A.TABLE_TYPE = 'BASE TABLE'
)
select 'DBCC CHECKIDENT ('''+A.[SCHEMA]+'.'+a.[TABLE]+''', reseed)' command
, ROW_NUMBER() OVER(ORDER BY a.[SCHEMA], a.[TABLE] asc) AS ID
, A.Curr_Value
, a.[TABLE]
into #temp
from cte A
ORDER BY A.[SCHEMA], A.[TABLE]
declare #i int = 1, #count int = (select max(ID) from #temp)
declare #text varchar(max) = ''
select #COUNT= count(1) FROM #temp
WHILE #I <= #COUNT
BEGIN
SET #text = (SELECT command from #temp where ID=#I)
EXEC (#text + ';')
print #text
select Curr_Value OldValue, ident_current([TABLE]) FixValue, [TABLE] from #temp where ID=#I
SET #I = #I + 1
SET #text='';
END
go
maybe someone or something with enough permissions made a mistake by reseeding?
As simple as this:
create table testid (
id int not null identity (1,1) primary key,
data varchar (3)
)
insert into testid (data) values ('abc'),('cde')
DBCC CHECKIDENT ('testid', RESEED, 1)
insert into testid (data) values ('bad')

I am getting Dollar sign unterminated

I want to create a function like below which inserts data as per the input given. But I keep on getting an error about undetermined dollar sign.
CREATE OR REPLACE FUNCTION test_generate
(
ref REFCURSOR,
_id INTEGER
)
RETURNS refcursor AS $$
DECLARE
BEGIN
DROP TABLE IF EXISTS test_1;
CREATE TEMP TABLE test_1
(
id int,
request_id int,
code text
);
IF _id IS NULL THEN
INSERT INTO test_1
SELECT
rd.id,
r.id,
rd.code
FROM
test_2 r
INNER JOIN
raw_table rd
ON
rd.test_2_id = r.id
LEFT JOIN
observe_test o
ON
o.raw_table_id = rd.id
WHERE o.id IS NULL
AND COALESCE(rd.processed, 0) = 0;
ELSE
INSERT INTO test_1
SELECT
rd.id,
r.id,
rd.code
FROM
test_2 r
INNER JOIN
raw_table rd
ON rd.test_2_id = r.id
WHERE r.id = _id;
END IF;
DROP TABLE IF EXISTS tmp_test_2_error;
CREATE TEMP TABLE tmp_test_2_error
(
raw_table_id int,
test_2_id int,
error text,
record_num int
);
INSERT INTO tmp_test_2_error
(
raw_table_id,
test_2_id,
error,
record_num
)
SELECT DISTINCT
test_1.id,
test_1.test_2_id,
'Error found ' || test_1.code,
0
FROM
test_1
WHERE 1 = 1
AND data_origin.id IS NULL;
INSERT INTO tmp_test_2_error
SELECT DISTINCT
test_1.id,
test_1.test_2_id,
'Error found ' || test_1.code,
0
FROM
test_1
INNER JOIN
data_origin
ON
data_origin.code = test_1.code
WHERE dop.id IS NULL;
DROP table IF EXISTS test_latest;
CREATE TEMP TABLE test_latest AS SELECT * FROM observe_test WHERE 1 = 2;
INSERT INTO test_latest
(
raw_table_id,
series_id,
timestamp
)
SELECT
test_1.id,
ds.id AS series_id,
now()
FROM
test_1
INNER JOIN data_origin ON data_origin.code = test_1.code
LEFT JOIN
observe_test o ON o.raw_table_id = test_1.id
WHERE o.id IS NULL;
CREATE TABLE latest_observe_test as Select * from test_latest where 1=0;
INSERT INTO latest_observe_test
(
raw_table_id,
series_id,
timestamp,
time
)
SELECT
t.id,
ds.id AS series_id,
now(),
t.time
FROM
test_latest t
WHERE t.series_id IS DISTINCT FROM observe_test.series_id;
DELETE FROM test_2_error re
USING t
WHERE t.test_2_id = re.test_2_id;
INSERT INTO test_2_error (test_2_id, error, record_num)
SELECT DISTINCT test_2_id, error, record_num FROM tmp_test_2_error ORDER BY error;
UPDATE raw_table AS rd1
SET processed = case WHEN tre.raw_table_id IS null THEN 2 ELSE 1 END
FROM test_1 tr
LEFT JOIN
tmp_test_2_error tre ON tre.raw_table_id = tr.id
WHERE rd1.id = tr.id;
OPEN ref FOR
SELECT 1;
RETURN ref;
OPEN ref for
SELECT o.* from observe_test o
;
RETURN ref;
OPEN ref FOR
SELECT
rd.id,
ds.id AS series_id,
now() AS timestamp,
rd.time
FROM test_2 r
INNER JOIN raw_table rd ON rd.test_2_id = r.id
INNER JOIN data_origin ON data_origin.code = rd.code
WHERE o.id IS NULL AND r.id = _id;
RETURN ref;
END;
$$ LANGUAGE plpgsql VOLATILE COST 100;
I am not able to run this procedure.
Can you please help me where I have done wrong?
I am using squirrel and face the same question as you.
until I found that:
-- Note that if you want to create the function under Squirrel SQL,
-- you must go to Sessions->Session Properties
-- then SQL tab and change the Statement Separator from ';' to something else
-- (for intance //). Otherwise Squirrel SQL sends one piece to the server
-- that stops at the first encountered ';', and the server cannot make
-- sense of it. With the separator changed as suggested, you type everything
-- as above and end with
-- ...
-- end;
-- $$ language plpgsql
-- //
--
-- You can then restore the default separator, or use the new one for
-- all queries ...
--

TSQL - compare tables

I want to create a stored procedure that compares the results of two queries. If the results of the 2nd table can be found in the first, print 'YES', otherwise, print 'No'.
Table 1:
SELECT dbo.Roles.RoleName, dbo.UserRoles.RoleID
FROM dbo.Roles LEFT OUTER JOIN
dbo.UserRoles ON dbo.Roles.RoleID = dbo.UserRoles.RoleID
WHERE (dbo.Roles.PortalID = 0) AND (dbo.UserRoles.UserID = 2)
Table 2:
Declare #RowData as nvarchar(2000)
Set #RowData = ( SELECT EditPermissions FROM vw_XMP_DMS_Documents where DocumentID = 2)
Select Data
from dbo.split(#RowData, ',')
For example.
Table 1:
John
Jack
James
Table 2:
John
Sally
Jane
Print 'YES'
Is this possible?
I am using temporary tables because I dont know which format your tables has.
SELECT dbo.Roles.RoleName, dbo.UserRoles.RoleID
INTO #t1
FROM dbo.Roles LEFT OUTER JOIN
dbo.UserRoles ON dbo.Roles.RoleID = dbo.UserRoles.RoleID
WHERE (dbo.Roles.PortalID = 0) AND (dbo.UserRoles.UserID = 2)
Declare #RowData as nvarchar(2000)
Set #RowData = ( SELECT EditPermissions FROM vw_XMP_DMS_Documents where DocumentID = 2)
Select Data
INTO #t2
from dbo.split(#RowData, ',')
select case when exists (select 1 from #t1 where RoleName = t.Data) then 'yes' else 'no' end answer, Data
into #tmp
from #t2 t
select * from #tmp
I am not 100 % sure this is what you want. So I am guessing.
added this after understanding the question
if exists(select 1 from #t2 t2 join #t1 t1 on t1.RoleName = t2.data)
print 'permsGranted'
ELSE print 'permsNotGranted'

Implementing and applying a string split in T-SQL

I have this statement in T-SQL.
SELECT Bay From TABLE where uid in (
select B_Numbers from Info_Step WHERE uid = 'number'
)
I am selecting "multiple" BAYs from TABLE where their uid is equal to a string of numbers like this:
B_Numbers = 1:45:34:98
Therefore, I should be selecting 4 different BAYs from TABLE. I basically need to split the string 1:45:34:98 up into 4 different numbers.
I'm thinking that Split() would work, but it doesn't and I get a syntax error.
Any thoughts from the T-SQL gods would be awesome!
Here is an implementation of a split function that returns the list of numbers as a table:
http://rbgupta.blogspot.com/2007/03/split-function-tsql.html
Looks like this would set you on your way...
Here is a method that uses an auxiliary numbers table to parse the input string. The logic can easily be added to a function that returns a table. That table can then be joined to lookup the correct rows.
Step 1: Create the Numbers table
SET NOCOUNT ON
GO
IF EXISTS
(
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Numbers'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_TYPE = 'BASE TABLE'
)
BEGIN
DROP TABLE dbo.Numbers
END
GO
CREATE TABLE dbo.Numbers
(
Number smallint IDENTITY(1, 1) PRIMARY KEY
)
GO
WHILE 1 = 1
BEGIN
INSERT INTO dbo.Numbers DEFAULT VALUES
IF SCOPE_IDENTITY() = 32767
BEGIN
BREAK
END
END
GO
Step 2: Parse the Input String
CREATE FUNCTION dbo.ParseString(#input_string varchar(8000), #delim varchar(8000) = " ")
RETURNS TABLE
AS RETURN
(
SELECT Number
FROM dbo.Numbers
WHERE CHARINDEX
(
#delim + CONVERT(VARCHAR(12),Number) + #delim,
#delim + #input_string + #delim
) > 0
)
GO
**EXAMPLE**
SELECT * FROM dbo.ParseString('1:45:34:98',':')
Step 3: Use the results however you want/need
Number
------
1
34
45
98
End-To-End Example
Create function that returns the appropriate BNumber (of course change it to use the commented out SQL)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.GetBNumber (#uid int)
RETURNS VARCHAR(8000)
AS
BEGIN
RETURN '1:45:34:98'
--select B_Numbers from Info_Step WHERE uid = #uid
END
GO
Use the use functions to return the desired results
-- Using Test Data
SELECT N.Number FROM Numbers N
JOIN dbo.ParseString(dbo.GetBNumber(12345),':') Q ON Q.Number = N.Number
-- Using Your Data (Untested but should work.)
SELECT N.Bay
FROM TABLE N
JOIN dbo.ParseString(dbo.GetBNumber(ENTER YOU NUMBER HERE),':') Q ON Q.Number = N.uid
Results
Number
------
1
34
45
98
You should keep your arrays as rows but if I understand your question I think this will work.
SELECT
Bay
From
TABLE
join Info_Step
on B_Numbers like '%'+ uid +'%'
where
Info_Step.uid = 'number'
This query will do a full table scan because of the like operator.
What you can do is loop through the B_Numbers entries and do your own split on : Insert those entries into a temp table and then perform your query.
DECLARE #i int
DECLARE #start int
DECLARE #B_Numbers nvarchar(20)
DECLARE #temp table (
number nvarchar(10)
)
-- SELECT B_Numbers FROM Info_Step WHERE uid = 'number'
SELECT #B_Numbers = '1:45:34:98'
SET #i = 0
SET #start = 0
-- Parse out characters delimited by ":";
-- Would make a nice user defined function.
WHILE #i < len(#B_Numbers)
BEGIN
IF substring(#B_Numbers, #i, 1) = ':'
BEGIN
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start))
SET #start = #i + 1
END
SET #i = #i + 1
END
-- Insert last item
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start + 1))
-- Do query with parsed values
SELECT Bay FROM TABLE WHERE uid in (SELECT * FROM #temp)
You can even try this
declare #str varchar(50)
set #str = '1:45:34:98'
;with numcte as(
select 1 as rn union all select rn+1 from numcte where rn<LEN(#str)),
getchars as(select
ROW_NUMBER() over(order by rn) slno,
rn,chars from numcte
cross apply(select SUBSTRING(#str,rn,1) chars)X where chars = ':')
select top 1
Bay1 = SUBSTRING(#str,0,(select rn from getchars where slno = 1))
,Bay2 = SUBSTRING(#str,
(select rn from getchars where slno = 1) + 1,
(((select rn from getchars where slno = 2)-
(select rn from getchars where slno = 1)
)-1))
,Bay3 = SUBSTRING(#str,
(select rn from getchars where slno = 2) + 1,
(((select rn from getchars where slno = 3)-
(select rn from getchars where slno = 2)
)-1))
,Bay4 = SUBSTRING(#str,
(select rn from getchars where slno = 3)+1,
LEN(#str))
from getchars
Output:
Bay1 Bay2 Bay3 Bay4
1 45 34 98