LOGINPROPERTY#
Returns information about a SQL login: its failed sign-in attempts, its last sign-in and its default database and language.
Syntax#
LOGINPROPERTY ( 'login_name' , 'property_name' )
Arguments#
‘login_name’
Is the name of the Querona login to ask about. login_name is sysname and is matched ignoring case. Only a standard SQL login has these properties: a Windows login, a Microsoft Entra ID login and a service account answer NULL, as a Windows login does on SQL Server.
‘property_name’
Is the name of the property to return. property_name is nvarchar(128) and is matched ignoring case. It can be one of the following values.
Property |
Base type |
What Querona answers |
Difference from SQL Server |
|---|---|---|---|
|
int |
How many attempts for the login were refused since its last successful sign-in, from logon tracking; 0 when nothing has been recorded, NULL while tracking is off. |
Querona counts every refused attempt that named the login - a wrong password, a disabled account, an
attempt refused during a lockout or from a network the login is not trusted from - and the count is
merged across the nodes of a cluster. SQL Server counts wrong passwords only, only for a login with
|
|
datetime |
When an attempt for the login was last refused, in server time; the sentinel |
The last refusal of any of the kinds counted above, not only a wrong password; the sentinel is the
plain date. Read under the same narrower rule as |
|
nvarchar |
|
None. |
|
nvarchar |
|
None. |
|
int, datetime |
NULL: Querona has no lock on a login. The failed sign-in lockout rate-limits a login and origin pair on one node and is not a lock on the login. |
SQL Server reports 0 or 1 and the moment the login was locked out. |
|
int, int, int, datetime |
NULL: Querona does not expire passwords. |
SQL Server reports the expiry and must-change state of a login with |
|
int |
NULL: Querona keeps no password history. |
SQL Server reports the policy’s history length for a login with |
|
varbinary |
NULL, whoever asks: Querona never discloses a credential. |
SQL Server returns the hash to a caller with |
|
int |
NULL: Querona stores passwords in its own format, which has no SQL Server algorithm code. |
SQL Server reports the version of its hash. |
Querona adds three property names for what SQL Server has no property for. On SQL Server they are unknown names and answer NULL, so a query that uses them runs on both.
Property |
Base type |
What Querona answers |
|---|---|---|
|
datetime |
When the login last signed in successfully, in server time; the sentinel |
|
nvarchar |
The protocol the last successful sign-in came in over: |
|
nvarchar |
The program name the client of the last successful sign-in declared; NULL when the login has not signed in, the client declared none, or tracking is off. |
Any other property name returns NULL.
Return types#
sql_variant
The base type of the value is the one listed for the property. NULL is returned, never an error, when either argument is NULL, the property is unknown, the login does not exist, the login is not a standard SQL login, or the caller may not see the login.
Remarks#
Which logins a caller may see is the rule SQL Server applies to sys.sql_logins: a login always sees
itself and the login named admin (as every login sees sa on SQL Server), and a caller holding
ALTER ANY LOGIN or VIEW ANY DEFINITION sees every login. Every other login answers NULL.
VIEW SERVER STATE does not widen this, although it does show every session’s previous sign-in in
sys.dm_exec_sessions. The rule goes by the name: an installation that renamed its administrator at
setup has no login that everyone sees, and a login created later under the name admin is visible to
everyone. sys.server_principals is not narrowed and still lists every login.
Five properties are read under a narrower rule: BadPasswordCount, BadPasswordTime and the three
Querona properties of the last sign-in. Another login’s, the admin login’s included, are answered only
to a caller holding ALTER ANY LOGIN or VIEW ANY DEFINITION; a login always reads its own. They are
judged together because they describe one thing - when a login signs in and how often an attempt for it is
refused - and because the refusal count returns to zero at a successful sign-in, so a caller that may read
the count may also tell when the sign-in happened. SQL Server answers BadPasswordCount and
BadPasswordTime about its sa to every login; Querona does not, because its counter measures more:
it accumulates, it counts every refused attempt that named the login rather than wrong passwords only, and it
is merged across a cluster.
A datetime property is reported in server time. One whose event never happened returns
1900-01-01 00:00:00, wherever the server runs. SQL Server has been observed to report that sentinel
shifted by the offset of its host’s time zone (02:00:00 on a UTC+2 host), so test for the date rather
than for NULL or a fixed hour. Inside the sql_variant the value travels as datetime2, where SQL
Server’s base type is datetime; it reads as a date and time on every client, and
SQL_VARIANT_PROPERTY(..., 'BaseType') is not answered by Querona.
The logon-sourced properties come from logon tracking. They answer NULL while tracking is off, and the “nothing recorded” values - 0, the sentinel, NULL - for a login nothing has been recorded for.
Examples#
The calling login’s own failed attempts since it last signed in, and when it last did:
SELECT LOGINPROPERTY(SUSER_SNAME(), 'BadPasswordCount') AS bad_password_count,
LOGINPROPERTY(SUSER_SNAME(), 'BadPasswordTime') AS bad_password_time,
LOGINPROPERTY(SUSER_SNAME(), 'LastSuccessfulLogonTime') AS last_successful_logon_time;
Every SQL login with its last sign-in and the client it came from, for a caller holding ALTER ANY LOGIN
or VIEW ANY DEFINITION (any other caller gets its own row answered and NULL for the admin row); a
login that has never signed in shows the sentinel date:
SELECT name,
CAST(LOGINPROPERTY(name, 'LastSuccessfulLogonTime') AS datetime) AS last_successful_logon_time,
CAST(LOGINPROPERTY(name, 'LastLogonClientInterfaceName') AS nvarchar(128)) AS client_interface,
CAST(LOGINPROPERTY(name, 'LastLogonProgramName') AS nvarchar(128)) AS program_name
FROM sys.sql_logins
ORDER BY name;