User Defined Scalar functions in SQL - sql

I am new to SQL and am learning User Defined Functions in SQL
I have two tables and I have given the rows I have inserted to those tables.
--Table1
create table sql_exam(
exa_examid bigint not null primary key,
exa_name varchar(100) not null,
exa_maxmark decimal(5,2) not null,
exa_minmarkreqdforpass decimal(5,2) not null,
exa_examscheduletime datetime not null
)
--Rows inserted into Table1
insert into sql_exam(exa_examid,exa_name,exa_maxmark,exa_minmarkreqdforpass,exa_examscheduletime) values (1,'Maths',100,40,'2012-10-10 10:00')
insert into sql_exam(exa_examid,exa_name,exa_maxmark,exa_minmarkreqdforpass,exa_examscheduletime) values (2,'English',75,35,'2012-10-11 10:00')
--Table2
create table sql_studentmarks(
stm_studentid int not null primary key,
stm_examid bigint foreign key references sql_exam(exa_examid),
stm_mark decimal(5,2)
)
--Rows inserted into Table2
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (1,1,80)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (2,1,90)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (3,1,40)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (1,2,70)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (2,2,60)
insert into sql_studentmarks(stm_studentid,stm_examid,stm_mark) values (3,2,17)
I require a help about creating Scalar functions and I need to get
A scalar function which will return the Student ID of the student who got highest mark in 'Maths'
A tabular function which will return the student ID and marks gained by the student who got highest total mark.
Am just trying to learn SQL. I have tried - "
create function fnGetMathsHightest()
returns int
as
begin
declare #st_id int
return #st_id
end
select dbo.fnGetMathsHightest()
from sql_studentmarks
where stm_examid=1
group by stm_studentid
having stm_mark=max(stm_mark)
for the first one. It does not look good.

It looks like this what you want for 1.
CREATE FUNCTION ssfnGetStudenytId
(
-- Add the parameters for the function here
)
RETURNS int
AS
BEGIN
declare #vId as int
set #vId = Select stm_studentid from sql_studentmarks where stm_mark = (SELECT MAX( stm_mark )from sql_studentmarks )
RETURN #vId
END

Related

Insert values in inheritance tables

CREATE TABLE projeto.Person (
Person_Code INT IDENTITY(1,1) NOT NULL,
birthDate DATE NOT NULL,
Name VARCHAR(50) NOT NULL,
PRIMARY KEY (Person_Code)
)
CREATE TABLE projeto.Student (
Student_Code INT REFERENCES projeto.Person (Person_Code),
payment INT NOT NULL,
PRIMARY KEY (Student_Code),
)
CREATE TABLE projeto.teacher (
payment INT NOT NULL,
teacher_Code INT,
PRIMARY KEY (teacher_Code),
CHECK (payment > 350)
)
How do I insert values ​​in student, paying attention that a student has all person attributes? e.g. student has name, birth_date etc.
I tried this:
INSERT INTO projeto.Person VALUES
('1961-03-26', John Adam')
but this only adds in a person, and I can't tell if its a student or not.
I guess its how to get the recently inserted Person_Code that you are asking? In which case use scope_identity().
declare #BirthDate date, #Name varchar(50), #Payment int, #IsStudent bit, #IsTeacher bit, #NewPersonCode int;
-- SET THE RELEVANT VARIABLE VALUES
-- Insert person
insert into projeto.Person (BirthDate, [Name])
select #BirthDate, #Name;
-- Get the Person_Code of the new person record
set #NewPersonCode = scope_identity();
-- Insert Student record if a student
insert into projeto.Student (Student_Code, Payment)
select #NewPersonCode, #Payment
where #IsStudent = 1;
-- Insert Teacher record if a teacher
insert into projeto.Teacher (Teacher_Code, Payment)
select #NewPersonCode, #Payment
where #IsTeacher = 1;

In sql table insert two same values,if insert same value in 3rd time it not allow to insert that record

create table sample(id int primary key,name varchar(100))
insert into sample values(1,'a')
,(2,'a')
,(3,'d')
,(4,'b')
,(5,'b')
--insert into sample values(6,'a'),(7,'b')
this record is not allow to insert the table.it disply error
Easiest solution is to check the table if the value being inserted is already present in the table twice before the insert statement.
--Preparation
DECLARE #sample TABLE
(
id INT IDENTITY PRIMARY KEY --USE IDENTITY to auto increment your primary key
,name VARCHAR(100)
)
--Initial Values
INSERT INTO #sample
VALUES
('a')
,('a')
,('d')
,('b')
,('b')
DECLARE #name VARCHAR(100)
SET #name = 'a'
IF(SELECT COUNT(id) FROM #sample WHERE name = #name) <= 1
BEGIN
INSERT INTO #sample
VALUES (#name)
END
ELSE
BEGIN
SELECT 'Error: Name ''' + #name + ''' already exists twice. Only two same values are allowed in name field!'
END

SQL Server: Insert batch with output clause

I'm trying the following
Insert number of records to table A with a table-valued parameter (tvp). This tvp has extra column(s) that are not in A
Get the inserted ids from A and the corresponding extra columns in the the tvp and add them to another table B
Here's what I tried
Type:
CREATE TYPE tvp AS TABLE
(
id int,
otherid int,
name nvarchar(50),
age int
);
Tables:
CREATE TABLE A (
[id_A] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50),
[age] [int]
);
CREATE TABLE B (
[id_B] [int] IDENTITY(1,1) NOT NULL,
[id_A] [int],
[otherid] [int]
);
Insert:
DECLARE #a1 AS tvp;
DECLARE #a2 AS tvp
-- create a tvp (dummy data here - will be passed to as a param to an SP)
INSERT INTO #a1 (name, age, otherid) VALUES ('yy', 10, 99999), ('bb', 20, 88888);
INSERT INTO A (name, age)
OUTPUT
inserted.id_A,
inserted.name,
inserted.age,
a.otherid -- <== isn't accepted here
INTO #a2 (id, name, age, otherid)
SELECT name, age FROM #a1 a;
INSERT INTO B (id_A, otherid) SELECT id, otherid FROM #a2
However, this fails with The multi-part identifier "a.otherid" could not be bound., which I guess is expected because columns from other tables are not accepted for INSERT statement (https://msdn.microsoft.com/en-au/library/ms177564.aspx).
from_table_name
Is a column prefix that specifies a table included in the FROM clause of a DELETE, UPDATE, or MERGE statement that is used to specify the rows to update or delete.
So is there any other way to achieve this?
You cannot select value from a source table by using INTO operator.
Use OUTPUT clause in the MERGE command for such cases.
DECLARE #a1 AS tvp;
DECLARE #a2 AS tvp
INSERT INTO #a1 (name, age, otherid) VALUES ('yy', 10, 99999), ('bb', 20, 88888);
MERGE A a
USING #a1 a1
ON a1.id =a.[id_A]
WHEN NOT MATCHED THEN
INSERT (name, age)
VALUES (a1.name, a1.age)
OUTPUT inserted.id_A,
a1.otherId,
inserted.name,
inserted.age
INTO #a2;
INSERT INTO B (id_A, otherid) SELECT id, otherid FROM #a2

Handling bulk insert on a table with multiple input sources in SQL

I am performing bulk insert on a table in sql server 2012, at the same time i am picking the last inserted row with max() function and inserting it into another table , how to perform this when my table is getting data from multiple sources because while performing insertion into secondary table there is time delay while insertions are still happening in primary table so next time max() will pick up last updated row and i will loose some rows which are not max() but still inserted into primary table meanwhile.
create table dbo.emp
(
id int primary key identity(1,1),
emp_id int,
name varchar(255),
address varchar(255)
)
create table dbo.empx
(
id int primary key,
emp_id int foreign key references dbo.emp(id),
)
declare #temp int ;
set #temp=1;
while #temp<1000
begin
insert into dbo.emp(emp_id,name,address)values (100+#temp,'Ename'+LTRIM(STR(#temp)),'123 Sample Address'+LTRIM(STR(#temp)));
set #temp=#temp+1;
insert into dbo.empx select max(dbo.emp.id),max(dbo.emp.emp_id) from dbo.emp
end
Use OUTPUT Clause...
CREATE TABLE #empx
(Id INT ,emp_id VARCHAR(50))
DECLARE #temp INT ;
SET #temp=1;
WHILE #temp<1000
BEGIN
INSERT INTO dbo.emp(emp_id,name,address)
OUTPUT INSERTED.Id,INSERTED.emp_id INTO #empx(Id,emp_id)
VALUES (100+#temp,'Ename'+LTRIM(STR(#temp)),'123 Sample Address'+LTRIM(STR(#temp)));
SET #temp=#temp+1;
END
INSERT INTO dbo.empx(Id,emp_id)
SELECT Id,emp_id FROM #empx
Or Use a trigger
CREATE TRIGGER EmpLog
ON dbo.emp
AFTER Insert
AS
BEGIN
SET NOCOUNT ON;
Insert into dbo.empx (id,emp_id) Select id,emp_id from inserted;
END
GO

SQL 2 Inserts based on return of first

I am generating a series of Inserts based on data from an Excel file into SQL Server 2014
How do I get the value of the ID of the first INSERT to put into the second
Simplified example where Ontario is a Province of Canada:
Insert into country (Name) values('canada');
Insert into provinces (CountryId, Name) values (???,'ontario');
There are 100 inserts so performance is not an issue.
declare #countryid int
Insert into country (Name) values('canada');
SELECT #countryid = SCOPE_IDENTITY()
Insert into provinces (CountryId, Name) values (#countryid,'ontario');
the answer above from tshoemake shows how you can insert one record and get the result. If you want to insert many records in Country and then many records in provinces, you might want to have a look at the OUTPUT clause. You'll have to work out how to join in your list of provinces because this code will just add Ontario to every country:
create table __country
(
id int identity(1,1) primary key,
Name varchar(5000)
)
CREATE TABLE __Provinces (
countryid int,
name varchar(5000)
)
CREATE TABLE #tempIDs
(
id int
)
INSERT INTO __Country
OUTPUT inserted.id
INTO #tempIDs
values ('canada'), values('USA')
insert into __Provinces
select #tempIDs.id, 'ontario'
from #tempIDs
join __country
ON __country.id = #tempIDs.id
select * from __Provinces