Update table in stored procedure with the new data - sql

I have a stored procedure which I pass 3 parameters to, and exports the whole thing in this table, let's call it dbo.myFinalTable. I want to achieve two things:
Task #1:
I need to append data when i'm executing the procedure again with any parameters I'm passing.
I tried adding this at the end of my final table creation, but the total number of rows stays the same. What is there to be done?
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'myDatabase'
AND TABLE_NAME = 'dbo.myFinalTable'))
BEGIN
INSERT INTO dbo.myFinalTable
SELECT
someValues
FROM #tempInWhichIcalulate
ORDER BY someOtherStuff
END
Task #2:
I execute it like this:
execute [myStoredProcedure] 'someString', '123', '2013-03-14'
I want the query above to only append data if the columns id and theDate (from dbo.MyFinalTable; those columns have their data passed from the stored procedure, in this example values '123', '2013-03-14') don't have those values already there.
Note: my procedure declaration looks like this:
alter procedure [myStoredProcedure]
(#theString varchar (30),
#id varchar (10),
#theDate date)

If I understood your goal, this could be the query:
insert into dbo.myFinalTable
select
#theString as MyString,
#id as MyId,
#theDate as MyDate
where not exists(select * from dbo.myFinalTable
where MyId = #id
and MyDate = #theDate)

Related

How can we use SQL column value as part of sql statement stored in another column

I have a scenario where I need to execute queries on different tables using ETL tool.
I want to store all the required queries in control table.
As part of this, I want to include the column WatermarkValue as part of the value in the column Source_Query, so that I can dynamically use it for my execution. This is how my control table should look like.
Table Name: Metadata_Table
TableID
Source_Query
WatermarkValue
1
select * from dbo.cust_eventchanges where lastmodifieddate >{WatermarkValue}
2022-10-09T12:00:00
2
select * from dbo.cust_contacts where lastmodifieddate >{WatermarkValue}
2022-07-08T03:20:00
So when I run my metadata table like this
select * from Metadata_Table where TableID=1
the result should be like below.
select * from dbo.cust_eventchanges where lastmodifieddate >'2022-10-09T12:00:00'
I know we can do this by concatenating two columns. But I would like to know if this is achievable.
I couldn't able to figure out how to achieve this. Hence, I need help on this scenario
Using sp_executesql with a typed parameter definition reduces the risk of SQL Injection
Example below shows how to run one of your queries. You could simply wrap this in a cursor where each iteration executes a different query in the metadata table.
DROP TABLE IF EXISTS #MetaData_Table
GO
CREATE TABLE #MetaData_Table
(TableID INT,Source_Query NVARCHAR(MAX),WatermarkValue DATETIME)
INSERT INTO #MetaData_Table
(TableID,Source_Query,WatermarkValue)
VALUES
(1,'select * from dbo.cust_eventchanges where lastmodifieddate >#WatermarkValue','2022-10-09T12:00:00'),
(2,'select * from dbo.cust_contacts where lastmodifieddate >#WatermarkValue','2022-07-08T03:20:00')
SELECT * FROM #MetaData_Table
DECLARE #dtVariable DATETIME;
DECLARE #SQLString NVARCHAR(500);
DECLARE #ParmDefinition NVARCHAR(500);
-- You can put this in a cursor to loop through all your tables, this is hardcoded to one for simplicity.
SELECT #SQLString = Source_Query, #dtVariable = WatermarkValue FROM #MetaData_Table WHERE TableID = 1
SET #ParmDefinition = N'#WatermarkValue DATETIME'
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#WatermarkValue = #dtVariable;
You can create a view and use a view in your ETL tool instead of the table.
create view vMetadataQueries
as
select TableID, Source_Query + WatermarkValue as [ExecuteQuery]
from Metadata_Table
This is not a particularly good way of doing that because it potentially leaves you open to SQL injection.

Need to log identifiers from select query recordset along with date/time stamp

I would like to log all records generated by a sql select statement in an SSRS report into a table for later reference at the time the report is run.
One idea is to append the unique ID to the reference table and then perform the full query with the additional data for the full record set, but i feel like there is probably a better way.
One way would be to use a STORED PROCEDURE for your SSRS report instead of hard coding the query in the RDL. Then, you could leverage the OUTPUT clause and log the query execution, and return the results. The proc would look something like this:
create procedure myProc (#param1 int)
as
begin
declare #resultTable table (id int, c1 char(4), c2 char(4))
insert into myloggingtable
output INSERTED.id, INSERTED.c2, INSERTED.c3 into #resultTable
select
id,
c1,
c2,
RunDateTime = getdate(),
from SomeTable
where id = #param1
select * from #resultTable
end
Here, I would have an auto-incremented key on the myloggingtable and the RunDateTime would be logged as the execution time.

Microsoft SQL Server - default value provided by stored procedure

Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure the parameters of which are values passed to insert into the row?
For example, I have table User:
| username | name | surname | id |
Insert looks like this:
INSERT INTO USER (username, name, surname)
VALUES ('myusername', 'myname', 'mysurname');
The id column is populated with an (integer) value retrieved by calling stored procedure mystoredproc with parameters myusername, myname, mysurname.
A further question is, would this stored procedure be called on each row, or can it be called in a grouped fashion. For example, I'd like my stored procedure to take the name and append a random integer to it so that that if I insert 100 users with the name 'David', they will get the same id and the stored procedure will be called only once. A bit of a bad example on the second point.
Good day,
Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure
Option 1: please check if this work for you
Specify Default Value for the Column and use "NOT NULL"
create trigger on the table AFTER INSERT
Inside the trigger, you can use the virtual table "inserted" in order to get the inserted values.
Using these values (using the inserted table) you can update the column using the logic you need for all the rows at once
** there is no need to use external SP probably, but you can execute SP from trigger if needed
** All executed by a trigger is in the same transaction as the original query.
would this stored procedure be called on each row
NO! The trigger will be executed once for all rows you insert in the same statement. The inserted table includes all the rows which were inserted. In your update section (step 4) you can update all the rows which were inserted in once and no need to execute something for each row
** If you do use external SP which is executed from the trigger then you can pass it all the inserted table as one using Table-Valued Parameter
------------------- update ---------------
Here is a full example of using this logic:
drop table if exists T;
CREATE TABLE T (id int identity(2,2), c int NOT NULL default 1)
GO
CREATE TRIGGER tr ON T AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
UPDATE T SET T.c = T2.C + 1
FROM inserted T2
INNER JOIN T T1 ON T1.id = T2.id
END
INSERT T(c) values (1) -- I insert the value 1 but the trigger will change it to 1+1=2
select * from T
GO
-- test multiple rows:
INSERT T(c) values (10),(20),(30),(40)
select * from T
GO
DECLARE #rc INT = 0,
#UserID INT = ABS(CHECKSUM(NEWID())) % 1000000 + 1;
WHILE #rc = 0
BEGIN
IF NOT EXISTS (SELECT 1 FROM dbo.Users WHERE UserId= #UserId)
BEGIN
INSERT dbo.Users(UserId) WHERE Username = #UserName SELECT #UserId;
SET #rc = 1;
END
ELSE
BEGIN
SELECT #UserId = ABS(CHECKSUM(NEWID())) % 1000000 + 1,
#rc = 0;
END
END

SQL Server stored procedure - delete rows based on multiple parameters

I need help figuring out how to build a stored procedure that will delete rows based on two parameters.
Assume I have two identical tables, Table1 and Table2 both containing columns Date, Name, and Number. I want to delete rows from Table1 based on Date and Name, and Insert Into Table1 From Table2.
Essentially I want it to function somewhere along the lines of:
Delete From Table1
Where (Table1.Date = Table2.Date) AND (Table1.Name = Table2.Name)
and then:
Insert Into Table1
Select * From Table2
I'm not familiar with how stored procedures work so I greatly appreciate the help.
Query for creating this kind of procedure goes like this:
CREATE PROCEDURE DummyProc
#Date DATE,
#Name VARCHAR(20) --Or NVARCHAR if you have UNICODE data
AS
BEGIN
DELETE FROM Table_1
WHERE Table_1.Date = #Date AND Table_1.Name= #Name
INSERT INTO Table_1
SELECT Date, Name, Number --You can specify columns
FROM Table_2
END
GO
And for executing with query:
EXEC dbo.DummyProc 'enter Date here', 'enter Name here';
GO

I am trying to run a query based on the results from a stored procedure

First, here is the code for sp_GetWorkQByUserName:
ALTER PROCEDURE [dbo].[sp_GetWorkQByUserName]
( #UserName varchar(50),
#StartDate datetime,
#EndDate datetime )
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT SpotId FROM tblSpotCount WHERE StoreNum = EXECUTE sp_GetUserLocationCodes(#UserName)
ORDER BY SpotDt ASC
END
I know my SELECT DISTINCT statement is wrong, but I wrote it like that to help show what I'm trying to do. I want to run this stored procedure based on the results from the sp_GetUserLocationCodes with a parameter of #UserName.
From what I can tell, my problem lies in how I'm calling sp_GetUserLocationCodes.
Question: how can I run a SELECT DISTINCT query on tblSpotCount.SpotId based on the results from the sp_GetUserLocationCodes stored procedure?
You cannot use a stored procedure directly in a query. You can, however, insert the results of a stored procedure into a temporary table and use that in your query:
CREATE TABLE #storeLocations
(
-- appropriate column names and data types go here
)
INSERT INTO #storeLocations (put column list here)
EXECUTE sp_GetUserLocationCodes(#UserName)
SELECT DISTINCT SpotId
FROM tblSpotCount
WHERE EXISTS (SELECT 1
FROM #storeLocations
WHERE #storeLocations.StoreNum = tblSpotCount.StoreNum)
ORDER BY SpotDt ASC
DROP TABLE #storeLocations