AX rules: find the AX system tables in any schema (AX 3.0 uses bmssa)
AX 3.0 owns its tables as the database user bmssa (bmssa.SQLDICTIONARY), so looking only in dbo never recognised a real AX 3.0 database. Detection now uses sys.tables by name in any schema; later AX versions in dbo still match. Tested against mock AX 3.0 (bmssa, int RECID), AX 4+ (dbo, bigint RECID) and a plain database. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
25a67cb98b
commit
f362862b33
1 changed files with 10 additions and 9 deletions
|
|
@ -2,8 +2,9 @@
|
||||||
//
|
//
|
||||||
// The agent has no data access (grant-least-privilege.sql), so these rules only read metadata and DMVs. They run in
|
// The agent has no data access (grant-least-privilege.sql), so these rules only read metadata and DMVs. They run in
|
||||||
// every user database, so an AX database is recognised without naming its tables directly (that would fail to compile
|
// every user database, so an AX database is recognised without naming its tables directly (that would fail to compile
|
||||||
// elsewhere): OBJECT_ID() of the AX system tables SQLDICTIONARY, DATAAREA and SYSCONFIG. AX 3.0 is told apart from
|
// elsewhere): the AX system tables SQLDICTIONARY, DATAAREA and SYSCONFIG in sys.tables, in ANY schema: AX 3.0 owns its
|
||||||
// AX 4.0 and later by RECID being 32-bit (int) instead of 64-bit (bigint).
|
// tables as the database user bmssa (bmssa.SQLDICTIONARY), later versions use dbo. AX 3.0 is told apart from AX 4.0
|
||||||
|
// and later by RECID being 32-bit (int) instead of 64-bit (bigint).
|
||||||
//
|
//
|
||||||
// Everything is SQL Server 2005 syntax (no CONCAT, IIF or STRING_AGG): AX 3.0 typically runs on 2000 or 2005.
|
// Everything is SQL Server 2005 syntax (no CONCAT, IIF or STRING_AGG): AX 3.0 typically runs on 2000 or 2005.
|
||||||
[
|
[
|
||||||
|
|
@ -12,7 +13,7 @@
|
||||||
"title": "Dynamics AX 3.0 er uden support fra Microsoft",
|
"title": "Dynamics AX 3.0 er uden support fra Microsoft",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)) AS [sql_version] WHERE OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL AND COLUMNPROPERTY(OBJECT_ID(N'dbo.SQLDICTIONARY'), N'RECID', 'Precision') = 10",
|
"query": "SELECT CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)) AS [sql_version] WHERE EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG') AND COLUMNPROPERTY((SELECT TOP 1 object_id FROM sys.tables WHERE name = N'SQLDICTIONARY'), N'RECID', 'Precision') = 10",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "{database} er en Dynamics AX 3.0-database, og AX 3.0 er uden support",
|
"findingTitle": "{database} er en Dynamics AX 3.0-database, og AX 3.0 er uden support",
|
||||||
"explanation": "Microsoft Dynamics AX 3.0 er for længst ude af Microsofts support, også den udvidede. Der kommer ingen sikkerhedsopdateringer eller rettelser til AX-kernen, klienten eller AOS, og nyere Windows- og SQL Server-versioner er aldrig testet med AX 3.0. AX 3.0 bruger desuden 32-bit RecId (int), som kan løbe tør på store installationer.",
|
"explanation": "Microsoft Dynamics AX 3.0 er for længst ude af Microsofts support, også den udvidede. Der kommer ingen sikkerhedsopdateringer eller rettelser til AX-kernen, klienten eller AOS, og nyere Windows- og SQL Server-versioner er aldrig testet med AX 3.0. AX 3.0 bruger desuden 32-bit RecId (int), som kan løbe tør på store installationer.",
|
||||||
|
|
@ -25,7 +26,7 @@
|
||||||
"title": "Dynamics AX 3.0 kører på en SQL Server-version, der ikke var understøttet til AX 3.0",
|
"title": "Dynamics AX 3.0 kører på en SQL Server-version, der ikke var understøttet til AX 3.0",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)) AS [sql_version], d.compatibility_level AS [compatibility_level] FROM sys.databases d WHERE d.database_id = DB_ID() AND CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)), 4) AS int) > 9 AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL AND COLUMNPROPERTY(OBJECT_ID(N'dbo.SQLDICTIONARY'), N'RECID', 'Precision') = 10",
|
"query": "SELECT CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)) AS [sql_version], d.compatibility_level AS [compatibility_level] FROM sys.databases d WHERE d.database_id = DB_ID() AND CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)), 4) AS int) > 9 AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG') AND COLUMNPROPERTY((SELECT TOP 1 object_id FROM sys.tables WHERE name = N'SQLDICTIONARY'), N'RECID', 'Precision') = 10",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "AX 3.0-databasen {database} ligger på SQL Server {sql_version}",
|
"findingTitle": "AX 3.0-databasen {database} ligger på SQL Server {sql_version}",
|
||||||
"explanation": "AX 3.0 blev kun frigivet til SQL Server 2000 og 2005. På nyere versioner kan den virke, men optimizeren, låsning og udfasede funktioner opfører sig anderledes end det, AX-kernen blev bygget til, og hverken Microsoft eller en AX-partner kan give support. Fejl viser sig ofte først under belastning, fx ved månedsafslutning. Databasens compatibility level er {compatibility_level}.",
|
"explanation": "AX 3.0 blev kun frigivet til SQL Server 2000 og 2005. På nyere versioner kan den virke, men optimizeren, låsning og udfasede funktioner opfører sig anderledes end det, AX-kernen blev bygget til, og hverken Microsoft eller en AX-partner kan give support. Fejl viser sig ofte først under belastning, fx ved månedsafslutning. Databasens compatibility level er {compatibility_level}.",
|
||||||
|
|
@ -38,7 +39,7 @@
|
||||||
"title": "Dynamics AX-database på en instans, hvor MAXDOP ikke er 1 (SQL Server 2005-2014)",
|
"title": "Dynamics AX-database på en instans, hvor MAXDOP ikke er 1 (SQL Server 2005-2014)",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT CAST(c.value_in_use AS int) AS [maxdop] FROM sys.configurations c WHERE c.name = 'max degree of parallelism' AND CAST(c.value_in_use AS int) <> 1 AND CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)), 4) AS int) < 13 AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL",
|
"query": "SELECT CAST(c.value_in_use AS int) AS [maxdop] FROM sys.configurations c WHERE c.name = 'max degree of parallelism' AND CAST(c.value_in_use AS int) <> 1 AND CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(128)), 4) AS int) < 13 AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG')",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "MAXDOP er {maxdop} på instansen med Dynamics AX-databasen {database}",
|
"findingTitle": "MAXDOP er {maxdop} på instansen med Dynamics AX-databasen {database}",
|
||||||
"explanation": "Dynamics AX sender mange små, hyppige forespørgsler og cursorer fra AOS. Når de får parallelle planer, bruger de flere tråde end nødvendigt, venter på hinanden (CXPACKET) og holder låse længere, så brugerne oplever langsomme formularer og blokering. Microsofts vejledning for Dynamics AX er derfor max degree of parallelism = 1 på instansen.",
|
"explanation": "Dynamics AX sender mange små, hyppige forespørgsler og cursorer fra AOS. Når de får parallelle planer, bruger de flere tråde end nødvendigt, venter på hinanden (CXPACKET) og holder låse længere, så brugerne oplever langsomme formularer og blokering. Microsofts vejledning for Dynamics AX er derfor max degree of parallelism = 1 på instansen.",
|
||||||
|
|
@ -55,7 +56,7 @@
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"minimumVersion": "13.0",
|
"minimumVersion": "13.0",
|
||||||
"query": "SELECT CAST(c.value_in_use AS int) AS [server_maxdop], CAST(s.value AS int) AS [database_maxdop] FROM sys.configurations c CROSS JOIN sys.database_scoped_configurations s WHERE c.name = 'max degree of parallelism' AND s.name = 'MAXDOP' AND (CASE WHEN CAST(s.value AS int) = 0 THEN CAST(c.value_in_use AS int) ELSE CAST(s.value AS int) END) <> 1 AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL",
|
"query": "SELECT CAST(c.value_in_use AS int) AS [server_maxdop], CAST(s.value AS int) AS [database_maxdop] FROM sys.configurations c CROSS JOIN sys.database_scoped_configurations s WHERE c.name = 'max degree of parallelism' AND s.name = 'MAXDOP' AND (CASE WHEN CAST(s.value AS int) = 0 THEN CAST(c.value_in_use AS int) ELSE CAST(s.value AS int) END) <> 1 AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG')",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "Dynamics AX-databasen {database} kører med MAXDOP større end 1",
|
"findingTitle": "Dynamics AX-databasen {database} kører med MAXDOP større end 1",
|
||||||
"explanation": "Dynamics AX sender mange små, hyppige forespørgsler og cursorer fra AOS. Når de får parallelle planer, bruger de flere tråde end nødvendigt, venter på hinanden (CXPACKET) og holder låse længere. Microsofts vejledning for Dynamics AX er MAXDOP 1. Instansen har {server_maxdop}, og databasen har {database_maxdop} (0 = instansens værdi gælder).",
|
"explanation": "Dynamics AX sender mange små, hyppige forespørgsler og cursorer fra AOS. Når de får parallelle planer, bruger de flere tråde end nødvendigt, venter på hinanden (CXPACKET) og holder låse længere. Microsofts vejledning for Dynamics AX er MAXDOP 1. Instansen har {server_maxdop}, og databasen har {database_maxdop} (0 = instansens værdi gælder).",
|
||||||
|
|
@ -71,7 +72,7 @@
|
||||||
"title": "Dynamics AX-tabeller uden unikt RecId-indeks",
|
"title": "Dynamics AX-tabeller uden unikt RecId-indeks",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT COUNT(*) AS [tables], LEFT(STUFF((SELECT TOP 10 N', ' + t2.name FROM sys.tables t2 WHERE COLUMNPROPERTY(t2.object_id, N'RECID', 'ColumnId') IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys.indexes i JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE i.object_id = t2.object_id AND i.is_unique = 1 AND c.name = N'RECID') ORDER BY t2.name FOR XML PATH('')), 1, 2, ''), 400) AS [examples] FROM sys.tables t WHERE COLUMNPROPERTY(t.object_id, N'RECID', 'ColumnId') IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys.indexes i JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE i.object_id = t.object_id AND i.is_unique = 1 AND c.name = N'RECID') AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL HAVING COUNT(*) > 0",
|
"query": "SELECT COUNT(*) AS [tables], LEFT(STUFF((SELECT TOP 10 N', ' + t2.name FROM sys.tables t2 WHERE COLUMNPROPERTY(t2.object_id, N'RECID', 'ColumnId') IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys.indexes i JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE i.object_id = t2.object_id AND i.is_unique = 1 AND c.name = N'RECID') ORDER BY t2.name FOR XML PATH('')), 1, 2, ''), 400) AS [examples] FROM sys.tables t WHERE COLUMNPROPERTY(t.object_id, N'RECID', 'ColumnId') IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys.indexes i JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id AND ic.is_included_column = 0 JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE i.object_id = t.object_id AND i.is_unique = 1 AND c.name = N'RECID') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG') HAVING COUNT(*) > 0",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "{tables} AX-tabeller i {database} har intet unikt indeks på RECID",
|
"findingTitle": "{tables} AX-tabeller i {database} har intet unikt indeks på RECID",
|
||||||
"explanation": "AX identificerer hver post med RecId og opretter normalt et unikt indeks på den (I_<tabel-id>RECID) ved synkronisering. Mangler det, er en synkronisering typisk fejlet eller afbrudt, eller indekset er fjernet manuelt. Uden det bliver opslag på RecId (som AX laver hele tiden, fx ved opdatering og sletning af én post) til scanninger, og dubletter opdages ikke. Eksempler: {examples}.",
|
"explanation": "AX identificerer hver post med RecId og opretter normalt et unikt indeks på den (I_<tabel-id>RECID) ved synkronisering. Mangler det, er en synkronisering typisk fejlet eller afbrudt, eller indekset er fjernet manuelt. Uden det bliver opslag på RecId (som AX laver hele tiden, fx ved opdatering og sletning af én post) til scanninger, og dubletter opdages ikke. Eksempler: {examples}.",
|
||||||
|
|
@ -84,7 +85,7 @@
|
||||||
"title": "Store Dynamics AX-tabeller uden clustered index (heaps)",
|
"title": "Store Dynamics AX-tabeller uden clustered index (heaps)",
|
||||||
"severity": "Medium",
|
"severity": "Medium",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT COUNT(*) AS [tables], SUM(h.row_count) AS [rows], LEFT(STUFF((SELECT TOP 10 N', ' + OBJECT_NAME(h2.object_id) + N' (' + CAST(h2.row_count AS nvarchar(20)) + N')' FROM (SELECT p.object_id, SUM(p.rows) AS row_count FROM sys.partitions p JOIN sys.tables t ON t.object_id = p.object_id WHERE p.index_id = 0 GROUP BY p.object_id) h2 WHERE h2.row_count >= 100000 ORDER BY h2.row_count DESC FOR XML PATH('')), 1, 2, ''), 400) AS [largest] FROM (SELECT p.object_id, SUM(p.rows) AS row_count FROM sys.partitions p JOIN sys.tables t ON t.object_id = p.object_id WHERE p.index_id = 0 GROUP BY p.object_id) h WHERE h.row_count >= 100000 AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL HAVING COUNT(*) > 0",
|
"query": "SELECT COUNT(*) AS [tables], SUM(h.row_count) AS [rows], LEFT(STUFF((SELECT TOP 10 N', ' + OBJECT_NAME(h2.object_id) + N' (' + CAST(h2.row_count AS nvarchar(20)) + N')' FROM (SELECT p.object_id, SUM(p.rows) AS row_count FROM sys.partitions p JOIN sys.tables t ON t.object_id = p.object_id WHERE p.index_id = 0 GROUP BY p.object_id) h2 WHERE h2.row_count >= 100000 ORDER BY h2.row_count DESC FOR XML PATH('')), 1, 2, ''), 400) AS [largest] FROM (SELECT p.object_id, SUM(p.rows) AS row_count FROM sys.partitions p JOIN sys.tables t ON t.object_id = p.object_id WHERE p.index_id = 0 GROUP BY p.object_id) h WHERE h.row_count >= 100000 AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG') HAVING COUNT(*) > 0",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "{tables} store AX-tabeller i {database} har intet clustered index",
|
"findingTitle": "{tables} store AX-tabeller i {database} har intet clustered index",
|
||||||
"explanation": "En tabel uden clustered index (en heap) får spredte data og 'forwarded records', når poster opdateres, og den kan ikke defragmenteres med en indeks-rebuild. I AX styres det af tabellens ClusterIndex-egenskab i AOT, som i AX 3.0 ofte ikke er sat på standard- og kundetabeller. På store tabeller giver det langsomme opslag og mere I/O. I alt {rows} rækker. Største: {largest}.",
|
"explanation": "En tabel uden clustered index (en heap) får spredte data og 'forwarded records', når poster opdateres, og den kan ikke defragmenteres med en indeks-rebuild. I AX styres det af tabellens ClusterIndex-egenskab i AOT, som i AX 3.0 ofte ikke er sat på standard- og kundetabeller. På store tabeller giver det langsomme opslag og mere I/O. I alt {rows} rækker. Største: {largest}.",
|
||||||
|
|
@ -97,7 +98,7 @@
|
||||||
"title": "Automatiske statistikker er slået fra i en Dynamics AX-database",
|
"title": "Automatiske statistikker er slået fra i en Dynamics AX-database",
|
||||||
"severity": "High",
|
"severity": "High",
|
||||||
"scope": "Database",
|
"scope": "Database",
|
||||||
"query": "SELECT CASE WHEN d.is_auto_create_stats_on = 1 THEN 'til' ELSE 'fra' END AS [auto_create_statistics], CASE WHEN d.is_auto_update_stats_on = 1 THEN 'til' ELSE 'fra' END AS [auto_update_statistics] FROM sys.databases d WHERE d.database_id = DB_ID() AND (d.is_auto_create_stats_on = 0 OR d.is_auto_update_stats_on = 0) AND OBJECT_ID(N'dbo.SQLDICTIONARY', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.DATAAREA', N'U') IS NOT NULL AND OBJECT_ID(N'dbo.SYSCONFIG', N'U') IS NOT NULL",
|
"query": "SELECT CASE WHEN d.is_auto_create_stats_on = 1 THEN 'til' ELSE 'fra' END AS [auto_create_statistics], CASE WHEN d.is_auto_update_stats_on = 1 THEN 'til' ELSE 'fra' END AS [auto_update_statistics] FROM sys.databases d WHERE d.database_id = DB_ID() AND (d.is_auto_create_stats_on = 0 OR d.is_auto_update_stats_on = 0) AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SQLDICTIONARY') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'DATAAREA') AND EXISTS (SELECT 1 FROM sys.tables WHERE name = N'SYSCONFIG')",
|
||||||
"subject": "database: {database}",
|
"subject": "database: {database}",
|
||||||
"findingTitle": "Automatiske statistikker er slået fra i AX-databasen {database}",
|
"findingTitle": "Automatiske statistikker er slået fra i AX-databasen {database}",
|
||||||
"explanation": "AX bygger sine forespørgsler dynamisk ud fra brugernes filtre, så optimizeren er helt afhængig af, at statistikkerne er der og er opdaterede. Uden automatiske statistikker vælger SQL Server ofte forkerte planer, især efter store kørsler som lageropgørelse og nummerserier, og formularer og batchjob kan pludselig blive meget langsomme. Auto create statistics: {auto_create_statistics}. Auto update statistics: {auto_update_statistics}.",
|
"explanation": "AX bygger sine forespørgsler dynamisk ud fra brugernes filtre, så optimizeren er helt afhængig af, at statistikkerne er der og er opdaterede. Uden automatiske statistikker vælger SQL Server ofte forkerte planer, især efter store kørsler som lageropgørelse og nummerserier, og formularer og batchjob kan pludselig blive meget langsomme. Auto create statistics: {auto_create_statistics}. Auto update statistics: {auto_update_statistics}.",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue