Prüfung über alle Tabellen: Int-Felder nah am Maximalwert?

Bild Microsoft Dynamics NAV 2016

Prüfung über alle Tabellen: Int-Felder nah am Maximalwert?

Beitragvon InfoWissler » 28. Oktober 2020 11:06

Vor ein paar Tagen hatten wir das unschöne Problem, dass wir spontan ein "Entry No." - Primärschlüsselfeld in einer Tabelle in unserer Branchenlösung von Integer auf Biginteger erweitern mussten (nicht weil wir wirklich über 2.147.483.647 Datensätze in der Tabelle hatten, sondern irgendjemand irgendwann Mist gebaut hat und die neuesten lfd. Nummern leider schon so hoch waren - es gibt riesige Lücken zwischen einzelnen lfd. Nummern).

Jetzt würden wir gerne einmal prüfen, ob uns das in einer anderen Tabelle möglicherweise ebenfalls droht. Kennt da evtl. jemand ein (SQL-)Skript, das für jedes Tabellenfeld mit dem Datentyp Integer prüft, ob da schon ein Wert > 2 Milliarden drin steht? Im Zweifel würde es auch erstmal reichen, das für Integer-Felder zu prüfen, die im Primärschlüssel vorkommen.

Vielen Dank!

Gefunden habe ich bisher das hier: https://stackoverflow.com/a/38614661/13260204

Allerdings fehlen da Tabellen, die auf jeden Fall ein Integer-Feld als Primärschlüssel haben, z.B. die Cust. Ledger Entry werden da nicht aufgeführt im Ergebnis.
InfoWissler
 
Beiträge: 141
Registriert: 5. November 2010 10:37
Bezug zu Microsoft Dynamics: End-Anwender
Microsoft Dynamics Produkt: Microsoft Dynamics NAV
Microsoft Dynamics Version: 2016

Re: Prüfung über alle Tabellen: Int-Felder nah am Maximalwer

Beitragvon Timo Lässer » 28. Oktober 2020 12:00

Wie man das als SQL-Script anstellt kann ich dir nicht sagen, jedoch wie man es in C/AL abbilden würde:

Ausgangsbasis ist die Tabelle "Field", welche du auf "Type=Integer" filterst.
Nun hast du alle Integer-Felder inklusive der dazugehörigen Tabellen-ID und kannst sie der Reihe nach abarbeiten.
Mit RecordRef und FieldRef kannst du jetzt dynamisch durch die Tabellen laufen.

Hinweis:
Wenn ihr mehrere Mandanten in der Datenbank habt, dann musst du die mandantenabhängigen Tabellen jeweils pro Mandant durchlaufen.
Ob eine Tabelle mandantenabhängig oder mandantenübergreifen definiert ist, kannst du der Tabelle "Table MetaData" entnehmen.
Gruß, Timo Lässer

Frage beantwortet? Schreibe bitte "[Gelöst]" vor den Titel deines ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, E-Mail, Instant Messanger, Soziale Netzwerke, Telefon oder Fax! Dafür ist dieses Forum da.
Hier kannst du für MSDynamics.de spenden.
Benutzeravatar
Timo Lässer
Administrator
Administrator
 
Beiträge: 5274
Registriert: 14. November 2004 22:18
Wohnort: DE 49716 Meppen
Arbeitsort: DE 49733 Haren (Ems)
Bezug zu Microsoft Dynamics: End-Anwender
Microsoft Dynamics Produkt: Microsoft Dynamics NAV
Microsoft Dynamics Version: 1.10a - 2018, BC14, BC21

Re: Prüfung über alle Tabellen: Int-Felder nah am Maximalwer

Beitragvon fiddi » 28. Oktober 2020 12:06

Hallo,

als Basis kannst du mal das Fieldcheck- Tool verwenden, das ist zwar für was ganz anders gedacht, der grundlegende Ablauf dürfte allerdings ähnlich sein.
fieldcheck (Mibuso)

Das Tool ist allerdings für den CC, dürfte sich aber einfach auf RTC bringen lassen.

Gruß Fiddi
Wer aufhört besser zu werden, hat aufgehört gut zu sein. (frei nach Philip Rosenthal)
Frage beantwortet? Schreibe bitte [Gelöst] vor den Titel des ersten Beitrags.
Bitte erst suchen, dann fragen. Bitte beachte den kleinen Community-Knigge.
Kein Support per PN, Mail, IM oder Telefon! Dafür ist dieses Forum da.
fiddi
Moderator
Moderator
 
Beiträge: 7091
Registriert: 9. Juni 2008 10:13
Realer Name: Hans Heinrich Fiddelke
Arbeitsort: Bremen
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics NAV
Microsoft Dynamics Version: NAV2.6-aktuell

Re: Prüfung über alle Tabellen: Int-Felder nah am Maximalwer

Beitragvon sweikelt » 28. Oktober 2020 12:39

InfoWissler hat geschrieben:Allerdings fehlen da Tabellen, die auf jeden Fall ein Integer-Feld als Primärschlüssel haben, z.B. die Cust. Ledger Entry werden da nicht aufgeführt im Ergebnis.

--> ich vermute mal ganz stark, weil es kein AutoIncrement ist! -> da müsstest du dann mit
Code: Alles auswählen
SELECT MAX(column_name)
FROM TableXYZ


ran
Benutzeravatar
sweikelt
Microsoft Partner
Microsoft Partner
 
Beiträge: 1776
Registriert: 18. November 2010 10:15
Wohnort: Oschatz
Realer Name: Stephan Weikelt
Arbeitsort: Berlin
Bezug zu Microsoft Dynamics: Microsoft Partner
Microsoft Dynamics Produkt: Microsoft Dynamics NAV
Microsoft Dynamics Version: 3-2018 | D365BC

Re: Prüfung über alle Tabellen: Int-Felder nah am Maximalwer

Beitragvon InfoWissler » 28. Oktober 2020 16:05

Danke euch!

Habe einmal folgendes Skript gebastelt, eher der Art schnell & schmutzig.

Wichtige Hinweise dazu:
* Ich mache nur ein RecRef.FINDLAST; es sind also eigentlich nur die Feldwerte aussagekräftig, bei denen der Primärschlüssel so aufgebaut ist, dass die höchsten Werte durch das Findlast gefunden werden und dann halt auch nur für Primärschlüsselfelder á la "Entry No." interessant. Gibt es da noch einen Weg, um quasi ein "Max-Lookup" zu machen, um alle Fälle erkennen zu können?
* Tabellennamen, die mit CRM beginnen, habe ich aufgrund von folgendem Fehler rausgenommen: "Die Tabellenverbindung für den Tabellentyp CRM muss mithilfe von RegisterTableConnection oder des Cmdlet New-NAVTableConnection registriert werden, bevor sie verwendet werden kann."


Code: Alles auswählen
NewFile.CREATE('\\Netzlaufwerk\IntegerValues.csv');
lim := ';';
NewFile.TEXTMODE(TRUE);

Field.SETRANGE(Type, Field.Type::Integer);
Field.SETRANGE(Class, Field.Class::Normal);
Field.SETRANGE(Enabled, TRUE);
Field.SETFILTER(TableName, '<>CRM*');
Functions.Progressbar('INIT', 'Feldnr.', Field.COUNT, 0, '');
Field.FIND('-');
REPEAT
  Functions.Progressbar('UPDATE', '', 0, 100, COPYSTR(Field.TableName + ' ' + Field.FieldName,1,20));
  IF OldTableNo <> Field.TableNo THEN BEGIN
    RecRef.CLOSE;
    RecRef.OPEN(Field.TableNo);
  END;
  IF RecRef.READPERMISSION THEN BEGIN
    IF NOT RecRef.ISEMPTY THEN BEGIN
      RecRef.FINDLAST;
      FRef := RecRef.FIELD(Field."No.");
      NewFile.WRITE(Field.TableName + lim + Field.FieldName + lim + FORMAT(FRef.VALUE));
    END;
  END;
  OldTableNo := Field.TableNo;
 
UNTIL Field.NEXT = 0;
Functions.Progressbar('CLOSE', '', 0, 0, '');
NewFile.CLOSE;


Variablen:
Name DataType Subtype Length
Field Record Field
RecRef RecordRef
FRef FieldRef
NewFile File
lim Text
OldTableNo Integer

Functions ist eine Codeunit bei uns mit der Funktion Progressbar, die mit ein paar Parametern sehr universal funktioniert, sodass man nicht jeden Fortschrittsbalken neu programmieren muss.

Zu dem SQL-Max-Befehl: da bin ich leider nicht versiert genug, um ein SQL-Skript zu bauen, dass das für alle Integer-Felder aller Tabellen macht.



Hier ein SQL-Skript:
Code: Alles auswählen
USE <Database>
GO

DECLARE @DatabaseName VARCHAR(100)
DECLARE @SchemaName VARCHAR(100)
DECLARE @TableName VARCHAR(100)
DECLARE @ColumnName VARCHAR(100)
DECLARE @FullyQualifiedTableName VARCHAR(500)
DECLARE @DataType VARCHAR(50)

--Create Temp Table to Save Results
IF OBJECT_ID('tempdb..#Results') IS NOT NULL
    DROP TABLE #Results

CREATE TABLE #Results (
    DatabaseName VARCHAR(100)
    ,SchemaName VARCHAR(100)
    ,TableName VARCHAR(100)
    ,ColumnName VARCHAR(100)
    ,ColumnDataType VARCHAR(50)
    ,MaxValue VARCHAR(50)
    ,MinValue VARCHAR(50)
    )

DECLARE Cur CURSOR
FOR
SELECT DB_Name() AS DatabaseName
    ,s.[name] AS SchemaName
    ,t.[name] AS TableName
    ,c.[name] AS ColumnName
    ,'[' + DB_Name() + ']' + '.[' + s.name + '].' + '[' + t.name + ']' AS FullQualifiedTableName
    ,d.[name] AS DataType
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types d ON c.user_type_id = d.user_type_id
WHERE d.name LIKE '%int%'
    OR d.name LIKE '%float%'
    OR d.name LIKE '%decimal%'
    OR d.name LIKE '%numeric%'
    OR d.name LIKE '%real%'
    OR d.name LIKE '%money%'
    AND is_identity = 0

OPEN Cur

FETCH NEXT
FROM Cur
INTO @DatabaseName
    ,@SchemaName
    ,@TableName
    ,@ColumnName
    ,@FullyQualifiedTableName
    ,@DataType

WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @SQL VARCHAR(MAX) = NULL

    SET @SQL = ' Select ''' + @DatabaseName + ''' AS DatabaseName, ''' + @SchemaName + ''' AS TableName,
      ''' + @TableName + ''' AS SchemaName,
      ''' + @ColumnName + ''' AS ColumnName,
      ''' + @DataType + ''' AS ColumnName,
      (Select MAX([' + @ColumnName + ']) from ' + @FullyQualifiedTableName + ' with (nolock))
      AS MaxValue,
      (Select MIN([' + @ColumnName + ']) from ' + @FullyQualifiedTableName + ' with (nolock))
      AS MaxValue'

    PRINT @SQL

    INSERT INTO #Results
    EXEC (@SQL)

    FETCH NEXT
    FROM Cur
    INTO @DatabaseName
        ,@SchemaName
        ,@TableName
        ,@ColumnName
        ,@FullyQualifiedTableName
        ,@DataType
END

CLOSE Cur

DEALLOCATE Cur

SELECT *
FROM #Results
    --drop table #Results


(Angepasst für Groß-/Kleinschreibung von hier: http://www.techbrothersit.com/2016/03/h ... r-all.html)
InfoWissler
 
Beiträge: 141
Registriert: 5. November 2010 10:37
Bezug zu Microsoft Dynamics: End-Anwender
Microsoft Dynamics Produkt: Microsoft Dynamics NAV
Microsoft Dynamics Version: 2016


Zurück zu NAV 2016

Wer ist online?

Mitglieder in diesem Forum: Unbekannter Spider und 1 Gast