How to find last inserted row in SQL server without identity column - c#

I have created table like below:
create table EmployeeDetails
(
id int,
name varchar(50),
designation varchar(50),
ReportingTo int
)
And inserted rows like this:
insert into EmployeeDetails values(1, 'A', 'Developer', 3)
insert into EmployeeDetails values(5, 'E', 'CEO', 5)
insert into EmployeeDetails values(2, 'B', 'Developer', 3)
insert into EmployeeDetails values(3, 'C', 'Manager', 4)
insert into EmployeeDetails values(4, 'D', 'S.Manager', 5)
My question is: how can I identify the last inserted row in the table?
Used queries:
select IDENT_CURRENT('EmployeeDetails')
Select SCOPE_IDENTITY()
But I still didn't find the answer.
Replies are always welcome

You have a fundamental misunderstanding of tables in relational databases. They represent unordered sets. So, there is no "last row" in a table. The information on the ordering of rows has to be included when you create the table and/or load data into it.
In SQL Server, the simplest method is an identity column. That is why many tables are defined as:
create table EmployeeDetails (
id int identity primary key,
name varchar(50),
designation varchar(50),
ReportingTo int
);
You can also add default insertion time columns:
create table EmployeeDetails (
id int identity primary key,
name varchar(50),
designation varchar(50),
ReportingTo int,
CreatedAt datetime default gettime()
);
However, you can have multiple rows with the same datetime value.

You also can use rowversion like below,if you add a column
CREATE TABLE MyTest (myKey int
,myValue int, RV rowversion);
GO
INSERT INTO MyTest (myKey, myValue) VALUES (1, 0);
GO
INSERT INTO MyTest (myKey, myValue) VALUES (2, 0);
select * from mytest order by rv desc
Note:
This always give the last row inserted/Updated
References:
rowversion

Add fields of type datetime with name CreateDate and UpdateDate in your table, when you insert record in your table set their value for getdate()
After that you can run queries:
Select top 10 * from YourTable Order By CreateDate DESC
Or for last updated
Select top 10 * from YourTable Order By UpdateDate DESC

Please find my answer as below. Hope this may help you.
Add one more column to store record creation date/time as below.
create table EmployeeDetails
(
id int,
name varchar(50),
designation varchar(50),
ReportingTo int,
CreatedOn datetime
)
After table creation and inserting records write/execute query (here inner query is used) as below
select
*
from EmployeeDetails
where CreatedOn = (select max(CreatedOn) from EmployeeDetails )

Related

Best way to get value for inserting into foreign key SQLite c#

When you have two tables with a foreign key for example
CREATE TABLE departments
( department_id INTEGER PRIMARY KEY AUTOINCREMENT,
department_name VARCHAR
);
CREATE TABLE employees
( employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name VARCHAR NOT NULL,
first_name VARCHAR,
department_id INTEGER,
CONSTRAINT fk_departments
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
);
Then when you insert data like this:
INSERT INTO departments VALUES (30, 'HR');
INSERT INTO departments VALUES (999, 'Sales');
INSERT INTO employees VALUES (10000, 'Smith', 'John', 30);
INSERT INTO employees VALUES (10001, 'Anderson', 'Dave', 999);
What is the best way of finding the values 30 and 999 when inserting into the emplyees table?
Here is an example using the sqlite last_insert_id() function (I'm going to clean this up to show that it really is an auto-number value, rather than a department number you already know):
begin transaction;
insert into departments (department_name) values ('HR');
insert into employees values (10000, 'Smith','John',last_insert_rowid());
insert into departments (department_name) values ('Sales');
insert into employees values (10001, 'Anderson','Dave',last_insert_rowid());
commit;
Another strategy is to use your departments names, so you can avoid worrying about knowing the ids at all (I will assume you add a unique constraint so that department names must be unique - which is sensible):
insert into departments values (30, 'HR');
insert into departments values (999, 'Sales');
insert into employees
select
10000,
'Smith',
'John',
(select department_id
from departments
where department_name = 'HR');
insert into employees
select
10001,
'Anderson',
'Dave',
(select department_id
from departments where department_name = 'Sales');

How to make a SQL query to display two columns values to one column?

I have a table structure like that as shown below. I want to show names under parent of names (where parent is ledger group)
DECLARE #t1 TABLE
(
ParentGroup varchar(20),
LedgerName varchar(20),
TotalDebit float,
credit float
)
INSERT INTO #t1
SELECT *
FROM Table1
INSERT INTO #t1
SELECT Distinct ParentGroup, ParentGroup, NULL, NULL
FROM Table1
Select LedgerName, TotalDebit, credit from #t1
group by LedgerName, TotalDebit, credit
ORDER BY (CASE WHEN TotalDebit IS NULL THEN 0 ELSE TotalDebit END)

How to get before and after insert unique ID from output clause while inserting

How can one get before and after insert unique ID from output clause while inserting?
For example: I have a table named A, I need to copy some of the records via
insert into select statement
and I need to get old unique id and new unique id in to a temp table using
OUTPUT Clause
This means I need to get return type as before insert unique identifier and after inert unique identifier. For that, I tried using below query as
DECLARE #MyTableVar TABLE
(
newid UNIQUEIDENTIFIER,
oldid UNIQUEIDENTIFIER
);
INSERT A (name, description)
output inserted.guid,
d.guid
INTO #MyTableVar
SELECT name, description
FROM A d
WHERE deptID = 550;
SELECT *
FROM #MyTableVar
But I am not able to get d.guid in output clause. Please correct me if there are any other options to get before and after insert unique id as output.
You should use column names from table.In your case ,you are using Inserted.Guid which should throw syntax error
create table tt
(
id varchar(300) default newid()
)
declare #t table
(
id varchar(300)
)
insert into tt
output inserted.* into #t
default values
select * from #t
You can use
##IDENTITY
to get after insert unique id as output.

Using the Inserted Value To Return A String From Lookup Sql

I have a stored procedure which inserts a customer into a SQL Server Database:
#Name varchar(50),
#Country int,
#DateRegistered datetime,
#NumberOfEmployees int,
#ID int output,
AS
INSERT INTO AccountManagementChristian.dbo.Customer(Name, CountryID, DateRegistered, EmployeeRangeID)
VALUES(#Name, #Country, #DateRegistered, #NumberOfEmployees)
SET #ID = ##IDENTITY
I also have a look up table with the Country ID and Country Name and another lookup table with the EmployeeRange ID and the Number of Employees. Both Country Name and Number of Employees are strings.
When inserting I need to be able to return the country name string that corresponds to the country ID that is inserted and the same for the Country Name and Country ID?
If I understand you right you need to insert the customer information in the stored procedure input variables then return the details for the newly inserted customer. In which case your INSERT for customer is right and instead of having an OUTPUT for the customer ID you need to SELECT the fields you want as in a normal select. The following should do what you want...
#Name varchar(50),
#Country int,
#DateRegistered datetime,
#NumberOfEmployees int
AS
DECLARE #ID INT -- moved this to be a standard variable
INSERT INTO AccountManagementChristian.dbo.Customer(Name, CountryID,
DateRegistered, EmployeeRangeID)
VALUES(#Name, #Country, #DateRegistered, #NumberOfEmployees)
SET #ID = ##IDENTITY
-- added this select to return the information you want,
-- using the #ID value to get details for the new customer
SELECT C.ID AS CustomerID, C.Name,
CL.ID AS CountryID, CL.CountryName,
ER.ID AS EmployeeRangeID, ER.NumberOfEmployees --, other fields required
FROM AccountManagementChristian.dbo.Customer AS C INNER JOIN
CountryLookup AS CL ON C.Country = CL.ID INNER JOIN
EmployeeRange AS ER ON C.EmployeeRangeID = ER.ID
WHERE C.ID = #ID
I am struggling to really understand where the "Insert Country return" option is coming in, since there is nothing here related to that. If you are, in fact, inserting the country and then using it, then just replicate the DECLARE #CustomerTab AND the OUTPUT INSERTED rows to catch that data. The updated script inserts the data and returns the fields I think you are asking for. Hope it helps. Below:
#Name varchar(50),
#Country int,
#DateRegistered datetime,
#NumberOfEmployees int,
#ID int output
AS
DECLARE #CustomerTab AS Table (CustomerID INT)
INSERT INTO AccountManagementChristian.dbo.Customer(Name, CountryID, DateRegistered, EmployeeRangeID)
OUTPUT
INSERTED.ID INTO #CustomerTab(CustomerId)
VALUES(#Name, #Country, #DateRegistered, #NumberOfEmployees)
--SET #ID = ##IDENTITY
select
Customer.Id
,Country.ID
,Country.[Country Name]
,EmployeeRange.[Number of Employees]
from
Customer
inner join
#CustomerTab CustomerTab
on
Customer.Id = CustomerTab.CustomerID
inner join
Country
on
Customer.CountryId = Country.Id
inner join
EmployeeRange
on
Customer.EmployeeRangeID = EmployeeRange.ID

How to default database value when system date change

I'm currently doing a banking website for my project, using C# and asp.net. One of the function is 'Remaining Daily Limit'. I need the database value to change back to default once I changed the system date to another day. Example : If a user had $500 (default value) as a daily limit, and he used all up. The next day, he will have $500 again. May I know how should I go about it?
Here is a SQL script that will create how I would setup your db with some sample data:
CREATE TABLE tblBankCustomer
(
BankCustomerId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, FirstName NVARCHAR(100) NOT NULL
, LastName NVARCHAR(100) NOT NULL
, DailySpendingLimit DECIMAL(38, 2) NOT NULL CONSTRAINT DF_tblBankCustomer_DailySpendingLimit DEFAULT(500)
)
CREATE TABLE tblTransactionType
(
TransactionTypeId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, TransactionType VARCHAR(50) NOT NULL
)
INSERT tblTransactionType (TransactionType)
VALUES ('Deposit')
, ('Withdrawal')
CREATE TABLE tblTransaction
(
TransactionId INT NOT NULL IDENTITY(1,1) PRIMARY KEY
, BankCustomerId INT NOT NULL
, TransactionDate DATE NOT NULL
, Amount DECIMAL(38, 2) NOT NULL
, TransactionTypeId INT NOT NULL
)
ALTER TABLE tblTransaction
ADD CONSTRAINT FX_tblTransaction_tblBankCustomer
FOREIGN KEY (BankCustomerId)
REFERENCES tblBankCustomer(BankCustomerId)
ALTER TABLE tblTransaction
ADD CONSTRAINT FX_tblTransaction_tblTransactionType
FOREIGN KEY (TransactionTypeId)
REFERENCES tblTransactionType(TransactionTypeId)
INSERT tblBankCustomer
(
FirstName
, LastName
)
VALUES ('Jeremy', 'Pridemore')
, ('K', 'YQ')
INSERT tblTransaction
(
BankCustomerId
, TransactionDate
, Amount
, TransactionTypeId
)
VALUES
(1, CURRENT_TIMESTAMP, 48.50, 2) -- Jeremy, Today, $48.50, Withdrawal
, (1, CURRENT_TIMESTAMP, 300.00, 2) -- Jeremy, Today, $300, Withdrawal
, (1, CURRENT_TIMESTAMP, -200.00, 1) -- Jeremy, Today, $200, Deposit
, (2, CURRENT_TIMESTAMP, 285.00, 2) -- K, Today, $285, Withdrawal
, (2, CURRENT_TIMESTAMP, 215.00, 2) -- K, Today, $215, Withdrawal
GO
CREATE FUNCTION fGetRemainingSpendingLimit
(
#BankCustomerId INT
, #Date DATE
)
RETURNS DECIMAL(38, 2)
BEGIN
SET #Date = ISNULL(#Date, CURRENT_TIMESTAMP)
DECLARE #RemainingLimit DECIMAL(38, 2) =
(SELECT
SUM([Transaction].Amount)
FROM tblBankCustomer Customer
INNER JOIN tblTransaction [Transaction]
ON [Transaction].BankCustomerId = Customer.BankCustomerId
AND [Transaction].TransactionDate = #Date
INNER JOIN tblTransactionType TransactionType
ON TransactionType.TransactionTypeId = [Transaction].TransactionTypeId
AND TransactionType.TransactionType = 'Withdrawal'
WHERE Customer.BankCustomerId = #BankCustomerId)
RETURN #RemainingLimit
END
GO
-- Some sample selects
SELECT dbo.fGetRemainingSpendingLimit(1, NULL)
SELECT dbo.fGetRemainingSpendingLimit(2, NULL)
Then in C# you should know the customer's ID for the customer you're working with. If you're using somethiing like ADO.NET you can call this function directly and use the value in code.
Default values are usually stay in some config file. In your specific case, I would say that you can
or have a table with default values
or in the tables where is possible to have restore functionality have default column with corresponding values.
after, can restore them using some stored procedure.
You can create SQL job and schedule it to run every midnight, within the job you can execute a stored procedure reseting values to $500.
In my opinion, based on that there may be other requirements in the future, I'd have a table that looks like:
UserID AppliedOn Limit
1 1/1/2012 500
1 2/1/2012 750
This give you a historic view of limits, that you can give to the user or data-mine. In the same way, that is how I would apply current daily limits.
UserID AppliedOn Withdrawn
1 1/10/2012 125
1 1/10/2012 225
Now on 1/1/2012 it would be easy to determine what the amount left in the limit is without any jobs or triggers. And again you'd have historic values that can be data-mined for other features.
SELECT
ul.Limit - uw.Sum as LimitLeft
FROM
UserLimit ul
INNER JOIN (
SELECT
UserID,
AppliedOn,
SUM(Limit) as Sum
FROM
UserLimit
Group by
UserID,
AppliedOn) uw on ul.UserID = uw.UserID
and ul.AppliedOn = uw.AppliedOn
WHERE
ul.UserID = #userID
AND ul.AppliedOn = #dateInQuestion
(my raw SQL skills might be a bit rusty due to Entity Framework here).

Categories

Resources