Getting only new data from SQL Server - sql-server

I've run my application which is getting data from SQL Server periodically. The problem here is that I want to get the records created since the last read.
Let me show an example.
At first, (at 12:00:00)
Table
---------
orderId orderName
1 name1
2 name2
3 name3
4 name3
I'm going to select all data here.
SELECT *
FROM TABLE
After one minute, some data was added into TABLE like below,
Table
---------
orderId orderName
1 name1
2 name2
3 name3
4 name3
5 name4
6 name5
At this point, when I select the data like below,
select *
from TABLE
what I want to get is row no. 5 and row no.6, which is added after I selected before.
My idea is I need to keep an identifier which indicates the transaction of id or something like that but I still don't catch any idea... Can you help me? Any keyword or links helping me?
It would be helpful for me to implement the refresh event to get only new data with the idea I'm expecting.
Thank you guys, here's the more specific table I have.
Table
---------
orderId orderTime
1 2017-9-4 8:00:00.000
1 2017-9-4 8:00:10.000
1 2017-9-4 8:00:20.000
1 2017-9-4 8:00:30.000
1 2017-9-4 8:00:40.000
1 2017-9-4 8:00:50.000
2 2017-9-4 8:00:11.000
2 2017-9-4 8:00:20.000
2 2017-9-4 8:00:32.000
2 2017-9-4 8:00:40.000
And the time records will be added continuously based on the orderId, respectively. Most idea that I keep the last orderId may not work for my case. How do I handle it in the specific this case?

There not any keyword to identify latest entry of last execution. Because, your query run both the time on different session. So, you can't identify it.
But Basically, we have other option to do this task.
Do it with Maintaining Max value of identifier. Maintain it into the variable, Session, Parameter, etc...
select *
from table
where orderId > yourvariableValue

You need to always save somewhere the largest orderId you've got at your last select and then, knowing that orderId, use it in your select, like this:
select ...
from ...
where orderId > 4

I see a lot of vague suggestions for saving in sessions, variables etc. I suggest you just use the table itself:
Find the last key in the local table:
SELECT ISNULL(MAX(OrderID),0) FROM TABLE
Use that to decide what to select out from your remote table
DECLARE #MaxID INT
SELECT #MaxID = ISNULL(MAX(OrderID),0) FROM TABLE
INSERT INTO TABLE (OrderID, Col1, Col2)
SELECT OrderID, Col1, Col2
FROM REMOTETABLE
WHERE OrderID > #MaxID
I see you have a recent edit saying this may not work. You need to explain why otherwise no one has any chance of helping. Is it because the OrderID might not always increment? Can it go backwards? You need to explain.

Store the last orderId and the associated last orderTime in a variable.
This should work as you want.
DECLARE #lastOrderId int = 2
DECLARE #lastOrderTime datetime = '2017-9-4 8:00:40.000'
SELECT * FROM Table
WHERE (orderId = #lastOrderId AND orderTime > #lastOrderTime) OR orderId > #lastOrderId
ORDER BY orderId, orderTime;

Related

How to add data to a single column

I have a question in regards to adding data to a particular column of a table, i had a post yesterday where a user guided me (thanks for that) to what i needed and said an update was the way to go for what i need, but i still can't achieve my goal.
i have two tables, the tables where the information will be added from and the table where the information will be added to, here is an example:
source_table (has only a column called "name_expedient_reviser" that is nvarchar(50))
name_expedient_reviser
kim
randy
phil
cathy
josh
etc.
on the other hand i have the destination table, this one has two columns, one with the ids and the other where the names will be inserted, this column values are null, there are some ids that are going to be used for this.
this is how the other table looks like
dbo_expedient_reviser (has 2 columns, unique_reviser_code numeric PK NOT AI, and name_expedient_reviser who are the users who check expedients this one is set as nvarchar(50)) also this is the way this table is now:
dbo_expedient_reviser
unique_reviser_code | name_expedient_reviser
1 | NULL
2 | NULL
3 | NULL
4 | NULL
5 | NULL
6 | NULL
what i need is the information of the source_table to be inserted into the row name_expedient_reviser, so the result should look like this
dbo_expedient_reviser
unique_reviser_code | name_expedient_reviser
1 | kim
2 | randy
3 | phil
4 | cathy
5 | josh
6 | etc.
how can i pass the information into this table? what do i have to do?.
EDIT
the query i saw that should have worked doesn't update which is this one:
UPDATE dbo_expedient_reviser
SET dbo_expedient_reviser.name_expedient_reviser = source_table.name_expedient_reviser
FROM source_table
JOIN dbo_expedient_reviser ON source_table.name_expedient_reviser = dbo_expedient_reviser.name_expedient_reviser
WHERE dbo_expedient_reviser.name_expedient_reviser IS NULL
the query was supposed to update the information into the table, extracting it from the source_table as long as the row name_expedient_reviser is null which it is but is doesn't work.
Since the Names do not have an Id associated with them I would just use ROW_NUMBER and join on ROW_NUMBER = unique_reviser_code. The only problem is, knowing what rows are null. From what I see, they all appear null. In your data, is this the case or are there names sporadically in the table like 5,17,29...etc? If the name_expedient_reviser is empty in dbo_expedient_reviser you could also truncate the table and insert values directly. Hopefully that unique_reviser_code isn't already linked to other things.
WITH CTE (name_expedient_reviser, unique_reviser_code)
AS
(
SELECT name_expedient_reviser
,ROW_NUMBER() OVER (ORDER BY name_expedient_reviser)
FROM source_table
)
UPDATE er
SET er.name_expedient_reviser = cte.name_expedient_reviser
FROM dbo_expedient_reviser er
JOIN CTE on cte.unique_reviser_code = er.unique_reviser_code
Or Truncate:
Truncate Table dbo_expedient_reviser
INSERT INTO dbo_expedient_reviser (name_expedient_reviser, unique_reviser_code)
SELECT DISTINCT
unique_reviser_code = ROW_NUMBER() OVER (ORDER BY name_expedient_reviser)
,name_expedient_reviser
FROM source_table
it is not posible to INSERT the data into a single column, but to UPDATE and move the data you want is the only way to go in that cases

Field is being updated with same value

I have a table that has a new column, and updating the values that should go in the new column. For simplicity sake I am reducing my example table structure as well as my query. Below is how i want my output to look.
IDNumber NewColumn
1 1
2 1
3 1
4 2
5 2
WITH CTE_Split
AS
(
select
*,ntile(2) over (order by newid()) as Split
from TableA
)
Update a
set NewColumn = a.Split
from CTE_Split a
Now when I do this I get my table and it looks as such
IDNumber NewColumn
1 1
2 1
3 1
4 1
5 1
However when I do the select only I can see that I get the desire output, now I have done this before to split result sets into multiple groups and everything works within the select but now that I need to update the table I am getting this weird result. Not quiet sure what I'm doing wrong or if anyone can provide any sort of feedback.
So after a whole day of frustration I was able to compare this code and table to another that I had already done this process to. The reason that this table was getting updated to all 1s was because turns out that whoever made the table thought this was supposed to be a bit flag. When it reality it should be an int because in this case its actually only two possible values but in others it could be more than two.
Thank you for all your suggestion and help and it should teach me to scope out data types of tables when using the ntile function.
Try updating your table directly rather than updating your CTE. This makes it clearer what your UPDATE statement does.
Here is an example:
WITH CTE_Split AS
(
SELECT
*,
ntile(2) over (order by newid()) as Split
FROM TableA
)
UPDATE a
SET NewColumn = c.Split
FROM
TableA a
INNER JOIN CTE_Split c ON a.IDNumber = c.IDNumber
I assume that what you want to achieve is to group your records into two randomized partitions. This statement seems to do the job.

SQL Server : recreate table in appropriate order

I've deleted some records (more precisely row 4) from a table in a SQL Server database. Now the first column goes like this (1,2,3,5) without row 4:
ID Name
------------
1 Luk
2 Sky
3 Philips
5 Andrey
How can I recreate this table and insert all data again in appropriate order?
Like this:
ID Name
--------
1 Luk
2 Sky
3 Philips
4 Andrey
EDIT:
But if i have another column (number) that is not a key, like this:
ID Number Name
------------
1 1 Luk
2 2 Sky
3 3 Philips
5 5 Andrey
Then can i recreate column Number and Name,
ID Number Name
------------
1 1 Luk
2 2 Sky
3 3 Philips
5 4 Andrey 'Can i do this, and if can HOW?
I would make a pretty strong case for never storing this number, since it is calculated, instead you could just create a view:
CREATE VIEW dbo.YourView
AS
SELECT ID,
Number = ROW_NUMBER() OVER(ORDER BY ID),
Name
FROM dbo.YourTable;
GO
This way after you have deleted rows, your view will already be in sync without having to perform any updates.
If you need to store the value, then almost the same query applies, but just placed inside a common table expression, which is then updated:
WITH CTE AS
( SELECT ID,
Number,
NewNumber = ROW_NUMBER() OVER(ORDER BY ID)
FROM dbo.YourTable
)
UPDATE CTE
SET Number = NewNumber;
You can use dbcc command
DBCC CHECKIDENT('tableName', RESEED, 0)
It would reset identity to 0.
Note it would require to truncate table first.
You can make the ID to auto increment which by default, the starting value for AUTO_INCREMENT is 1, and it will increment by 1 for each new record.
E.g MSSQL uses IDENTITY keyword to auto increment whereas MySQL uses the AUTO_INCREMENT keyword to perform an auto-increment feature.
MSSQL
ID int IDENTITY(1,1) PRIMARY KEY
MySQL
ID int NOT NULL AUTO_INCREMENT

How to automatically set the SNo of the row in MS SQL Server 2005?

I have a couple of rows in a database table (lets call it Customer). Each row is numbered by SNo, which gets automatically incremented by the identity property inherent in MS SQLServer. But when I delete a particular row that particular row number is left blank, but I want the table to auto correct itself.
To give you a example:
I have a sample Customer Table with following rows:
SNo CustomerName Age
1 Dani 28
2 Alex 29
3 Duran 21
4 Mark 24
And suppose I delete 3rd row the table looks like this:
SNo CustomerName Age
1 Dani 28
2 Alex 29
4 Mark 24
But I want the table to look like this:
SNo CustomerName Age
1 Dani 28
2 Alex 29
3 Mark 24
How can I achieve that?
Please help me out
Thanks in anticipation
As has been pointed out doing that would break anything in a relationship with SNo, however if your doing this because you need ordinal numbers in you presentation layer for example, you can pull off a [1..n] row number with;
SELECT ROW_NUMBER() OVER(ORDER BY SNo ASC), SNo, CustomerName, Age FROM Customer
Obviously in this case the row number is just an incrementing number, its meaningless in relation to anything else.
I don't think you want to do that. Imagine the scenario where you have another table CustomerOrder that stores all customer orders. The structure for that table might look something like this:
CustomerOrder
-------------
OrderID INT
SNo INT
OrderDate DATETIME
...
In this case, the SNo field is a foreign key into the CustomerOrder table, and we use it to relate orders to a customer. If you delete a record from your Customer table (say with SNo = 1), are you going to go back and update the SNo values in the entire CustomerOrder table? It's best to just let the ID's autoincrement and not worry about spaces in the IDs due to deletions.
Why not create a view?
CREATE VIEW <ViewName>
AS
SELECT
ROW_NUMBER() OVER(ORDER BY SNo ASC) AS SNo
,CustomerName
,Age
FROM Customers
GO
Then access the data in customers table by selecting from the view.
Of course the SNo shown by the view has no meaning in the context of relationships, but the data returned will look exactly like you want it to look.
Using transactions when inserting records in the Database with C#
You have to use DBCC CHECKIDENT(table_name, RESEED, next_val_less_1);
As have been pointed out in other answers, this is a bad idea, and if the reason is for a presentation there are other solutions.
-- Add data to temp table
select SNo, CustomerName, Age
into #Customer
from Customer
-- Truncate Customer
-- Resets identity to seed value for column
truncate table Customer
-- Add rows back to Customer
insert into Customer(CustomerName, Age)
select CustomerName, Age
from #Customer
order by SNo
drop table #Customer

how can i convert one row of a database to two

i have a table with the column id, itemID and locationId.
i have now split one locationId into multiple ones so i want to:
Update all records where locationId is 10 and have two rows where locationId is set to 11 and 12 (ItemId would be the same for both rows)
So to start i have:
Id ItemID LocationID
1 1 10
and i want to end up with
Id ItemID LocationID
1 1 11
1 1 12
is there any convenient way of doing this given its an update and an insert at once
Possibly there's a single statement that can do it but why wouldn't you just use transactions, a vendor-agnostic way:
begin transaction;
insert into TBL (id,itemid,locationid)
select id, itemid, 11
from TBL
where locationid = 10;
update TBL
set locationid = 12
where locationid = 10;
commit transaction;
I always tend to use standard SQL where possible so as to be able to switch between vendors easily, never mind the fact I haven't switched vendors for over a decade now :-)
Still, it's nice to have the ability even if I never use it (though sometimes I'll go vendor-specific for performance reasons if required - I don't think that'll be necessary for this particular use case since it's probably not something you'll be doing a lot of).

Resources