Create partition function based on join with other table - sql-server

I have 2 tables:
TableA
(
Id uniqueidentifier,
Date datetime
)
TabelB
(
Body XML,
KeyA uniqueidentifier
)
And I want to create partition for both tables based on date field in TableA.
I checked documentation but can't find any clue about it. Is it possible to do?

Related

T-SQL OUTPUT clause to update a temp table

I have a utility script that is used to insert data into tables in my database. The script has a number of temp table in it that stores the new data to be inserted and a lot of it is related.
So, for example I have tables like so
DECLARE #Table1 TABLE
(
Table1ID INT
Table1Description VARCHAR(50)
Table1Code VARCHAR(5)
)
DECLARE #Table2 TABLE
(
Table2ID INT
Table2Description VARCHAR(50)
Table2Code VARCHAR(5)
)
DECLARE #Relationships TABLE
(
Table1Code VARCHAR(5)
Table2Code VARCHAR(5)
)
So the script populates the data in #Table1 and #Table2, but doesn't populate the ID fields. Once the data has been MERGEd into the database tables, I update the Table1ID and Table2ID fields in a separate statement as they are auto incrementing fields. Then when I use the #Relationships table to populate the database table, I can join to #Table1 and #Table2 to get the actual ID values.
I'm updating the script and I'm wondering if I can MERGE the data from #Table1/#Table2 into the database and update the ID fields in the temp table as part of the MERGE statement using the OUTPUT clause all in one statement?
I think the answer is no as I can't find anything mentioning updating an existing table with the OUTPUT clause, only inserting into a table.
I am still able to do what I need to do, so I'm not after alternatives. I just wondering if it is possible using the OUTPUT Clause
Thanks in advance

Azure SQL table partitions Ignored when queries contain simple function

Using Azure SQL Server database. I have a few tables partitioned on a 90 day date boundary. We have a stored procedure to shift data to maintain the proper partition breakpoint/range. I'm using a small function to provide the proper date breakpoint for my queries so I don't have to constantly update all my views.
But just by virtue of using that function in my queries, partitioning is ignored. Do I have no choice but to put hard-coded values in my queries everywhere and constantly modify them?
Here is a sample that reproduces the problem.
Update: After changing the PartitionDate function below according to the marked answer, it was fine for a short time (partition elimination occurred). Then, queries started sucking again. When I ran simple queries filtered by the date function, partitions were no longer eliminated.
------------------------------- setup
-- Create functions PartitionDate and PartitionQueryDate
create function PartitionDate() returns date as
begin
return GETDATE() - 91 -- returns 1/4/2019 today
end
go
create function PartitionQueryDate() returns date as
begin
return GETDATE() - 90 -- returns 1/5/2019
end
go
-- Create partition func and scheme using above functions
CREATE PARTITION FUNCTION order_pf (smalldatetime) AS RANGE RIGHT FOR VALUES (dbo.PartitionDate())
CREATE PARTITION SCHEME order_ps AS PARTITION order_pf ALL TO ([PRIMARY])
-- Create Order (pk, OrderDate, Fk), Customer (pk) tables. Order is partitioned
create table Customer
(
id int primary key identity(1,1),
FirstName varchar(255) not null
)
create table [Order]
(
id int identity(1,1), OrderDate smalldatetime not null,
CustomerId int not null,
CONSTRAINT [FK_Orders_Customer] FOREIGN KEY ([CustomerId]) REFERENCES Customer([id])
) on order_ps(OrderDate);
-- Add in indexes to Order: only OrderDate on the partition func
CREATE CLUSTERED INDEX [Order_OrderDate] ON [Order]([OrderDate] ASC) ON [order_ps] ([OrderDate]);
CREATE NONCLUSTERED INDEX [FK_Order_Customer] ON [Order](CustomerId, OrderDate) ON [order_ps] ([OrderDate]) -- seems to work the same with or without the partition reference.
go
-- Add some data before and after the partition break
insert Customer values ('bob')
insert [Order] values('12-31-2018', SCOPE_IDENTITY())
insert Customer values ('hank')
insert [Order] values('1-6-2019', SCOPE_IDENTITY())
---------------------------- test
-- verify a row per partition:
SELECT $PARTITION.order_pf(OrderDate) as Partition_Number, COUNT(*) as Row_Count
FROM [Order]
GROUP BY $PARTITION.order_pf(OrderDate)
-- Simple queries with actual execution plan turned on. The queries are logically equivalent.
select COUNT(1) from [Order] where OrderDate > '1-5-2019' -- Index seek Order_OrderDate; actual partition count 1
select COUNT(1) from [Order] where OrderDate > dbo.PartitionQueryDate() -- Index seek Order_OrderDate; actual partition count 2
-- Cleanup
drop table if exists [Order]
drop table if exists Customer
drop partition scheme order_ps
drop partition function order_pf
drop function if exists PartitionDate
drop function if exists PartitionQueryDate
One workaround would be to assign the function result to a variable first.
declare #pqd smalldatetime = dbo.PartitionQueryDate();
select COUNT(1) from [Order] where OrderDate > #pqd
Another option would be to use an inline TVF
CREATE FUNCTION dbo.PartitionQueryDateTVF ()
RETURNS TABLE
AS
RETURN
(
SELECT CAST(CAST( GETDATE() - 90 AS DATE) AS SMALLDATETIME) AS Date
)
GO
SELECT COUNT(1) from [Order] where OrderDate > (SELECT Date FROM dbo.PartitionQueryDateTVF())
This may be something that is improved with inline scalar UDFs but I'm not in a position to test this at the moment

SQL Server how to populate data to table2 when table1 updated

I'm creating a table to store cars, and another table to store the time when the new car was added to the database, can someone please explain to me how to create the relationship to update time automatically when the car was created.
Create table Cars
(
CarID int Primary Key identity(1,1),
Make varchar(50),
Model varchar(50),
Colour varchar(59)
)
create Table TimeLogs
(
AddedOn SYSDATETIME(),
CarId int unique foreign key references Cars(CarId)
)
I would solve this by not using a second table for what should be a column in the Cars table. The table would be designed more appropriately like this.
Create table Cars
(
CarID int Primary Key identity(1,1),
Make varchar(50),
Model varchar(50),
Colour varchar(59),
AddedOn datetime default SYSDATETIME()
)
To automatically update one table whenever another table is updated, you need to use a TRIGGER.
You needs to use insert trigger for the same, as below
CREATE TRIGGER yourNewTrigger ON yourSourcetable
FOR INSERT
AS
INSERT INTO yourDestinationTable
(col1, col2 , col3, user_id, user_name)
SELECT
'a' , default , null, user_id, user_name
FROM inserted
go

Populating Row Number on new column for table without primary key

I have a table where I am adding a new column to indicate row numbers. This table doesn't have any primary key associated, so I am not sure how I can populate it with row number values.
Here is the code I have put in the CTE but in the primary table I don't know how to correlate the Id column. Id is the newly added column to which I need to start the numbering.
;with CTE_RowNum as (
select
ROW_NUMBER() OVER (ORDER BY NEWID()) AS RowId
,Id
from dbo.Test
)
I can partition the table on certain columns but how would I join such criteria with original table?
Edit- Here is the schema that I am referring to. Id is the newly added column which I want to populate with as row numbers. Name and Error column together form the uniqueness.
Expected Output would be -
1,ABC,Time Out Issue
2,ABC,Page Not Found
3,DEF,Page Not Found
The order doesn't matter, I mean the last row can have '1' and the others some other value.
The other way I can think of repopulating data into a new table with Identity inserted but was just wondering is there a way to do that through T-SQL?
CREATE TABLE #Test
(
Id INT
,Name NVARCHAR(100)
,Error NVARCHAR(100)
)
INSERT INTO #Test (Name,Error) VALUES
('ABC','Time Out Issue')
,('ABC','Page Not Found')
,('DEF','Page Not Found')
It's really simple:
;WITH cte AS
(
SELECT Id, ROW_NUMBER() OVER (ORDER BY NEWID()) AS RowId
FROM #test
)
UPDATE cte
SET Id = RowId

How to manually replicate two tables with identity fields

-- DUPLICATE OF Best way to get identity of inserted row? --
Well, I got an hard time finding a good title for this one.
I have two tables, with microsoft SQL server. Here's the structure:
TableA ( Id identity, Name varchar(20))
TableB ( Id identity, Name varchar(20))
Mapping ( IdTableA int, IdTableB int)
On TableA, I have an After Insert trigger. I want to "replicate" the insert into TableB, gets the new Ids and insert the mapping between the TableA's id and the TableB's id into the table Mapping.
I have no problem with inserting the data into TableB... but I have an hard time finding how to create a "map" between the two Ids...
Any help would be very appreciated.

Resources