I have a table Age_cal, Vaccine Information and Medical_information table as follows:
I am trying to write a stored procedure where, I will be able to insert the values into a table named vaccine based on the vaccine_information table.
In med_info table we have DOB, and the age is calculated and stored in age_cal table along with the age grp and medicalID (PK). The vaccine information table has name of vaccine and to which age group it needs to be given to.
So while inserting a value into Vaccine table, I want to give the values medicalId, date it was given on , dose no and facility name as parameters. But I want the vaccine name to be automatically selected based on the age group they belong to.
I have written the following stored procedure, but null value is getting inserted into the vaccine_name. Please help me with inserting the vaccine name using the stored procedure.
ALTER PROCEDURE [dbo].[allot_v]
#MedicalID int,
#VaccineDate date,
#DoseNo int,
#facilityName varchar(20)
AS
BEGIN
DECLARE #injectvaccine varchar(20)
SET #injectvaccine = (SELECT dbo.VaccineInformation.VaccineName
FROM dbo.VaccineInformation, dbo.Age_Cal
WHERE dbo.Age_Cal.grp = dbo.VaccineInformation.grp
AND dbo.Age_Cal.MedicalID = #MedicalID)
INSERT INTO [dbo].[Vaccination]
([MedicalID], [VaccineName], [VaccineDate], [DoseNo], [FacilityName])
VALUES (#MedicalID, #injectvaccine, #VaccineDate, #DoseNo, #facilityName)
END
The stored procedure worked with the following code:
ALTER PROCEDURE [dbo].[allot_v]
#MedicalID int,
#VaccineDate date,
#DoseNo int,
#facilityName varchar(20)
AS
BEGIN
DECLARE #injectvaccine varchar(20)
SET #injectvaccine = (SELECT dbo.VaccineInformation.VaccineName
FROM dbo.VaccineInformation, dbo.Age_Cal
WHERE dbo.Age_Cal.grp = dbo.VaccineInformation.grp
AND dbo.Age_Cal.MedicalID = #MedicalID)
-- Insert statements for procedure here
INSERT INTO [dbo].[Vaccination]
([MedicalID], [VaccineName], [VaccineDate], [DoseNo], [FacilityName])
VALUES (#MedicalID, #injectvaccine, #VaccineDate, #DoseNo, #facilityName)
END
Related
I am trying to run a report to get some metrics about our users and the different applications we have. Each of our customers have a different database so I need to run the same queries across several databases. The query I use works like a charm but then I need to manually copy and paste each of the results to make everything readable. So I thought I would create a temp table, then insert each query result into a different column in the table to also avoid duplicate code but somehow, most of the results returned are null or show numbers that do not much when running the query without using the temp table. Any ideas as to what I am might be doing wrong? Can't seem to figure it out
DROP TABLE #ReportAlexis
CREATE TABLE #ReportAlexis
(
CompanyName VARCHAR(MAX),
TotalUsers INT,
UsersSinceDate INT,
TotalAppUsers INT,
AppUsersSinceDate INT,
Number_of_Logins_SinceDate INT,
);
EXEC master.dbo.sp_msforeachdb 'if ''?'' in (''master'',''model'',''msdb'',''tempdb'') return
declare #startdate DATETIME = ''2019-01-01''
INSERT INTO #ReportAlexis(Companyname) Select companyname from CompanyTable where Databasename = ?;
USE ?;
INSERT INTO #ReportAlexis(TotalUsers) Select count (*) as TotalUsers from User;
INSERT INTO #ReportAlexis(UsersSinceDate) Select count (*) as UsersSinceDate from User where CreatedDate >= #startdate;
INSERT INTO #ReportAlexis(TotalAppUsers) Select count (*) as TotalAppUsers from Users where UserTypeID = 5;
INSERT INTO #ReportAlexis(AppUsersSinceDate) Select count (*) as AppUsersSinceDate from Users where UserTypeID = 5 and CreatedDate >= #startdate;
INSERT INTO #ReportAlexis(Number_of_Logins_SinceDate) Select count (*) as Number_of_Logins_SinceDate from UserLoginDetails where UserID in (Select UserID from Users where UserTypeID = 5) and LoginTime >= #startdate
'
SELECT * FROM #ReportAlexis
I assume the scope is disconnected, try a ##table (global temp table). the #table is only easily accessible within scope though the real name can be found in:
select t.name from tempdb.sys.tables t where t.name like '#ReportAlexis%'
/* it's still better to use a global temp table */
CREATE TABLE ##ReportAlexis
(
CompanyName VARCHAR(MAX),
TotalUsers INT,
UsersSinceDate INT,
TotalAppUsers INT,
AppUsersSinceDate INT,
Number_of_Logins_SinceDate INT,
);
I have three sql tables called financetrail , fooperson and idDog .All of them have the column idFoo :
I have created the following stored procedure
CREATE PROCEDURE [dbo].[getCustomerFinance] #idFinanceType INT
AS
BEGIN
SELECT idCustomer
FROM financetrail
where idFinanceType = #idFinanceType ;
END
GO
so i can dynamically choose customers of a certain finance type.
The above procedure generates a table along these lines:
I also have this query
SELECT firstName , lastName
FROM IdDog RIGHT JOIN fooPerson
ON IdDog.idFoo = fooPerson.idFoo WHERE IdDog.idIdDog IS NULL;
The result gives me all customers who don't have a dog in the dog table.
What i want to do ?
I want to create a stored procedure that would give me all the customers who don't have a valid idCard(query above) and are of a certain riskType defined from the stored procedure above .
What i have tried ?
I have tried doing the following :
ALTER PROCEDURE [dbo].[getMissingDogs]
AS
BEGIN
DECLARE #financeFilterTable table ( idCustomer INT)
INSERT INTO #financeFilterTable
EXEC getCustomerRisk 3
SELECT * FROM #financeFilterTable
SELECT firstName , lastName
FROM IdCard RIGHT JOIN FooPerson
ON IdCard.idCustomer = FooPerson.idFoo WHERE IdDog.idIdDog IS NULL;
END
and i get the following results :
In the current result set i have two tables . One table giving Customer ids for customers of a certain risk type and the second table giving the customers who don't have an idCard .
I want to find all customers who fulfill both criteria (have a certain risk type and not have an idCard ) in one table
Is that possible ?
I am not sure if I fully understand your requirement. Would it be possible please to post some sample data and expected query results?
Maybe the stored procecure below works for you?
ALTER PROCEDURE [dbo].[getMissingDogs]
#idFinanceType INT
AS
BEGIN
DECLARE #financeFilterTable table ( idCustomer INT)
INSERT INTO #financeFilterTable
EXEC getCustomerRisk #idFinanceType
SELECT firstName , lastName
FROM IdCard RIGHT JOIN FooPerson ON IdCard.idCustomer = FooPerson.idFoo
INNER JOIN #financeFilterTable AS RiskType ON RiskType.idCustomer = IdCard.idCustomer
WHERE IdDog.idIdDog IS NULL;
END
I have the following stored procedure, I have two tables here, Movie and Director. Both need to be updated when a new movie has been created or added. How do you handle FKs in stored procedures? The FK in this case is director_id. It is a primary key in Director but a FK in Movie Do I need to specify it twice like so? I am getting conflict errors
CREATE PROCEDURE Book_Book_Creation
#Book_id_arg DECIMAL(12),
#author_id_arg DECIMAL(12),
#type_id_arg DECIMAL(12),
#title_arg VARCHAR(64), -
#copyright_arg DECIMAL(4),
#dauthor_id_2_arg DECIMAL(12),
#author_fname_arg VARCHAR (64),
#author_lname_arg VARCHAR (64)
AS
BEGIN
INSERT INTO Book(Book_id, author_id,genre_id, title, copyright)
VALUES (#author_arg, #author_id_arg, #type_id_arg, #title_arg, #copyright_arg);
INSERT INTO Author(author_id, author_fname, author_lname)
VALUES (#director_id_2_arg, #director_fname_arg, #director_lname_arg)
END;
EXECUTE Book_Book_Creation 32,32,1,'Tempting',2013,32,'Taylor','Mendez';
Basically, you just need to do this:
insert into the Director table first
get the newly inserted ID from that table (assuming that the Director_Id column is your primary key and is of type INT IDENTITY)
then insert into the Movie table with that new ID
Something like this:
DECLARE #NewDirectorID INT
INSERT INTO Director (Director_id, Director_fname, director_lname)
VALUES (#director_id_2_arg, #director_fname_arg, #director_lname_arg)
SELECT #NewDirectorID = SCOPE_IDENTITY()
INSERT INTO Movie (Movie_id, director_id,genre_id, title, copyright)
VALUES (#movie_id_arg, #NewDirectorID, #genre_id_arg, #title_arg, #copyright_arg);
I don't see why you would pass in the director's ID as a parameter - twice!
Try this one -
ALTER PROCEDURE dbo.Movie_Movie_Creation12
#movie_id_arg DECIMAL(12),
#director_id_arg DECIMAL(12),
#genre_id_arg DECIMAL(12),
#title_arg VARCHAR(64),
#copyright_arg DECIMAL(4),
#director_fname_arg VARCHAR (64),
#director_lname_arg VARCHAR (64)
AS BEGIN
INSERT INTO dbo.Director (Director_id, Director_fname, director_lname)
SELECT #director_id_arg, #director_fname_arg, #director_lname_arg
INSERT INTO dbo.Movie (Movie_id, director_id,genre_id, title, copyright)
SELECT #movie_id_arg, #director_id_arg, #genre_id_arg, #title_arg, #copyright_arg
END
EXECUTE dbo.Movie_Movie_Creation12
#movie_id_arg = 32
, #director_id_arg = 32
, #genre_id_arg = 1
, #title_arg = 'Argo'
, #copyright_arg = 2012
, #director_fname_arg = 'Ben'
, #director_lname_arg = 'Affleck'
I have a stored procedure that looks up an article based on the article's title. But I also need to increment a column in the same table that counts the number of times the article is viewed.
Trying to be as efficient as possible, I see two possible ways to approach this:
Perform one SELECT to obtain the PK on the target row. Then use that PK to increment the number of views and, finally, another SELECT using the PK to return the article data.
Perform one SELECT to return the article data to my application, and then use the returned PK to make another round trip to the database to increment the number of views.
I know #1 would be pretty fast, but it's three lookups. And #2 requires two round trips to the database. Is there no way to optimize this task?
EDIT Based on feedback, I came up with the following. Thanks for any comments or constructive criticism.
DECLARE #Slug VARCHAR(250) -- Stored procedure argument
-- declare #UpdatedArticle table variable
DECLARE #UpdatedArticle TABLE
(
ArtID INT,
ArtUserID UNIQUEIDENTIFIER,
ArtSubcategoryID INT,
ArtTitle VARCHAR(250),
ArtHtml VARCHAR(MAX),
ArtDescription VARCHAR(350),
ArtKeywords VARCHAR(250),
ArtLicenseID VARCHAR(10),
ArtViews BIGINT,
ArtCreated DATETIME2(7),
ArtUpdated DATETIME2(7)
);
UPDATE Article
SET ArtViews = ArtViews + 1
OUTPUT
INSERTED.ArtID,
INSERTED.ArtUserID,
inserted.ArtSubcategoryID,
INSERTED.ArtTitle,
INSERTED.ArtHtml,
INSERTED.ArtDescription,
INSERTED.ArtKeywords,
INSERTED.ArtLicenseID,
INSERTED.ArtViews,
INSERTED.ArtUpdated,
INSERTED.ArtCreated
INTO #UpdatedArticle
WHERE ArtSlugHash = CHECKSUM(#Slug) AND ArtSlug = #Slug AND ArtApproved = 1
SELECT a.ArtID, a.ArtUserID, a.ArtTitle, a.ArtHtml, a.ArtDescription, a.ArtKeywords, a.ArtLicenseID,
l.licTitle, a.ArtViews, a.ArtCreated, a.ArtUpdated, s.SubID, s.SubTitle, c.CatID, c.CatTitle,
sec.SecID, sec.SecTitle, u.UsrDisplayName AS UserName
FROM #UpdatedArticle a
INNER JOIN Subcategory s ON a.ArtSubcategoryID = s.SubID
INNER JOIN Category c ON s.SubCatID = c.CatID
INNER JOIN [Section] sec ON c.CatSectionID = sec.SecID
INNER JOIN [User] u ON a.ArtUserID = u.UsrID
INNER JOIN License l ON a.ArtLicenseID = l.LicID
Here is a way using the OUTPUT statement (SQL Server 2005 onwards), in a single update statement:
IF OBJECT_ID ('Books', 'U') IS NOT NULL
DROP TABLE dbo.Books;
CREATE TABLE dbo.Books
(
BookID int NOT NULL PRIMARY KEY,
BookTitle nvarchar(50) NOT NULL,
ModifiedDate datetime NOT NULL,
NumViews int not null CONSTRAINT DF_Numviews DEFAULT (0)
);
INSERT INTO dbo.Books
(BookID, BookTitle, ModifiedDate)
VALUES
(106, 'abc', GETDATE()),
(107, 'Great Expectations', GETDATE());
-- declare #UpdateOutput1 table variable
DECLARE #UpdateOutput1 table
(
BookID int,
BookTitle nvarchar(50),
ModifiedDate datetime,
NumViews int
);
-- >>>> here is the update of Numviews and the Fetch
-- update Numviews in Books table, and retrive the row
UPDATE Books
SET
NumViews = NumViews + 1
OUTPUT
INSERTED.BookID,
INSERTED.BookTitle,
INSERTED.ModifiedDate,
INSERTED.NumViews
INTO #UpdateOutput1
WHERE BookID = 106
-- view updated row in Books table
SELECT * FROM Books;
-- view output row in #UpdateOutput1 variable
SELECT * FROM #UpdateOutput1;
I'm using MERGE in my query and i'm making INSERT on clause WHEN NOT MATCHED THEN, but then i would like to get the inserted row identity and make another INSERT to some other table. Query for now is:
ALTER PROCEDURE [dbo].[BulkMergeOffers]
#data ImportDataType READONLY
AS
SET NOCOUNT ON;
DECLARE #cid int = 0
MERGE dbo.oferta AS target
USING #data AS source
ON (target.nr_oferty = source.nr_oferty)
WHEN NOT MATCHED THEN
INSERT (nr_oferty,rynek,typ_transakcji, typ_nieruchomosci,cena,powierzchnia, rok_budowy, wojewodztwo, miasto, dzielnica, ulica, opis, wspolrzedne, film, zrodlo, KontaktStore, data, forma_wlasnosci, stan_techniczny, liczba_pokoi, liczba_peter, pietro, material, kuchnia, pow_dzialki, typ_dzialki, woda,gaz, prad,sila, przeznaczenie,lokal_dane)
VALUES (source.nr_oferty,source.rynek,source.typ_transakcji, source.typ_nieruchomosci,source.cena,source.powierzchnia, source.rok_budowy, source.wojewodztwo, miasto, source.dzielnica, source.ulica, source.opis, source.wspolrzedne, source.film, source.zrodlo, source.KontaktStore, source.data, source.forma_wlasnosci, source.stan_techniczny, source.liczba_pokoi, source.liczba_peter, source.pietro, source.material, source.kuchnia, source.pow_dzialki, source.typ_dzialki, source.woda,source.gaz, source.prad,source.sila, source.przeznaczenie,source.lokal_dane);
So as you see i need to insert some values to the target table based on source data, then i need to take the insert identity and insert it into another table but also based on some source data, so something like that, just after the first insert:
SET #cid = SCOPE_IDENTITY();
if source.photo is not null
begin
insert into dbo.photos(offerID, file) values (#cid, source.photo);
end
But i can't assemble it, a have no access to the source no more, also if statement show error :
"the multi-part identifier
source.photo can not be bound"
but it is there. Just for clarity ImportDataType is a table-valued parameter.
Please HELP
If you don't need the WHEN MATCHED part of the MERGE statement in your query, there's no real reason to use MERGE. You could use INSERT with an outer join or NOT EXISTS statement.
In either case, you can use the OUTPUT clause to retrieve the inserted identity value an pass it on to a second query.
I've extended your example:
<stored procedure header - unchanged>
--declare a table variable to hold the inserted values data
DECLARE #newData TABLE
(nr_oferty int
,newid int
) -- I'm guessing the datatype for both columns
MERGE dbo.oferta AS target
USING #data AS source
ON (target.nr_oferty = source.nr_oferty)
WHEN NOT MATCHED THEN
INSERT (nr_oferty,rynek,typ_transakcji, typ_nieruchomosci,cena,powierzchnia, rok_budowy, wojewodztwo, miasto, dzielnica, ulica, opis, wspolrzedne, film, zrodlo, KontaktStore, data, forma_wlasnosci, stan_techniczny, liczba_pokoi, liczba_peter, pietro, material, kuchnia, pow_dzialki, typ_dzialki, woda,gaz, prad,sila, przeznaczenie,lokal_dane)
VALUES (source.nr_oferty,source.rynek,source.typ_transakcji, source.typ_nieruchomosci,source.cena,source.powierzchnia, source.rok_budowy, source.wojewodztwo, miasto, source.dzielnica, source.ulica, source.opis, source.wspolrzedne, source.film, source.zrodlo, source.KontaktStore, source.data, source.forma_wlasnosci, source.stan_techniczny, source.liczba_pokoi, source.liczba_peter, source.pietro, source.material, source.kuchnia, source.pow_dzialki, source.typ_dzialki, source.woda,source.gaz, source.prad,source.sila, source.przeznaczenie,source.lokal_dane)
OUTPUT inserted.nr_oferty, inserted.<tableId> INTO #newData;
-- replace <tableId> with the name of the identity column in dbo.oftera
insert into dbo.photos(offerID, file)
SELECT nd.newid, pt.photo
FROM #data AS pt
JOIN #newData AS nd
ON nd.nr_oferty = pt.nr_oferty
WHERE pt.photo IS NOT NULL