I like @Turo's suggestion of using a view.
It could just consist of something like
CREATE VIEW dbo.TimeFilteredClient
AS
SELECT *
FROM dbo.Client
WHERE CAST(GETDATE() AS TIME) BETWEEN '09:00' AND '17:00'
Then grant Emily permissions on the view and not the table. As long as the view and table share the same owner she will be able to select from the view but get no results outside the specified time.
If you are on 2016 you could also use row level security on the table to achieve much the same thing. Example below
CREATE TABLE dbo.Client
(
clientId INT IDENTITY PRIMARY KEY,
Name VARCHAR(50)
);
INSERT dbo.Client
VALUES ('client1'),
('client2');
CREATE USER Emily WITHOUT LOGIN;
GRANT SELECT ON dbo.Client TO Emily;
GO
CREATE SCHEMA Security;
GO
CREATE FUNCTION Security.EmilyTimeFilterPredicate()
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT 1 AS fn_securitypredicate_result
WHERE USER_NAME() <> 'Emily'
OR CAST(GETDATE() AS TIME) BETWEEN '09:00' AND '17:00';
GO
CREATE SECURITY POLICY EmilyTimeFilter
ADD FILTER PREDICATE Security.EmilyTimeFilterPredicate()
ON dbo.Client
WITH (STATE = ON);
GO
EXECUTE AS USER = 'Emily';
SELECT *
FROM dbo.Client;
REVERT;
SELECT *
FROM dbo.Client;
GO
DROP SECURITY POLICY EmilyTimeFilter ;
DROP TABLE dbo.Client
DROP USER Emily
DROP FUNCTION Security.EmilyTimeFilterPredicate
DROP SCHEMA Security;