Skip to content

dbLinter

Catch and fix database problems before they hit production.

dbLinter is a tool suite for checking and improving the quality of database applications. Quality is assessed using static code analysis and database queries based on a centrally managed configuration.

dbLinter targets all versions of Oracle Database and PostgreSQL using a predefined, configurable ruleset that is based on the Trivadis Coding Guidelines.

Static Code Analysis

Analyse your SQL, PL/SQL, PL/pgSQL, SQL*Plus, SQLcl and psql files. Without connecting to a database.

SQL-based Tests

Run SQL queries against your database. Each result row represents a problem that needs to be solved.

Quick Fixes

Automatically apply quick fixes, migration scripts or mark problems to be ignored in subsequent analyses or test runs.

IDE Integration

Highlight problems while you code in VS Code, Cursor, Windsurf or Theia IDE. Providing explanations with links to coding guidelines and suggested fixes.

CI/CD Pipeline Integration

Integrating dbLinter into your build pipeline helps to block any changes that cause severe problems from reaching production.

SonarQube Integration

Provides seamless integration with any on-prem SonarQube edition. Enabling rule configuration, issue browsing, and enforcement through quality gates considering new code.

Predefined Rules

Extensive set of 180+ predefined rules, that can be enabled/disabled and parametrised. A rule is implemented as static code analysis check and/or SQL-based test.

Custom Rules

If the predefined rules are not enough, define your own. Either as static code analysis check, or SQL-based test, or both.

dbLinter is a joint project between Grisselbav and United Codes. You can get commercial subscriptions through United Codes. See the dbLinter product site for details.

Here are the features that come with the different subscription plans:

FeatureAnonymousStarterEssentialProfessional
Number of seatsunlimited11-n1-n
Number of configurations-1unlimitedunlimited
View rules and related datayesyesyesyes
Manage configurations-yesyesyes
Run checksyesyesyesyes
Run SQL-based tests-yesyesyes
Ignore chosen SQL-based test findings-yesyesyes
dbLinter VS Code extensionyesyesyesyes
Run all accessible checks and tests(preview)(preview)yesyes
Quick fixes in dbLinter VS Code extension(preview)(preview)yesyes
dbLinter CLI with SonarCloud integration-(preview)yesyes
Manage user access--yesyes
dbLinter SonarQube plugin---yes
Access to dbLinter test repository---yes
Custom rules, checks and SQL-based tests---yes
Generate Java project for checks and SQL-based tests---yes
Manage custom validators (plugins)---yes
Export rules and configurations---yes
Import rules and configurations---yes

The features marked with (preview) are only available during the preview phase.

The Anonymous plan is active when you use the dbLinter VS Code extension without setting up a dbLinter account. Only those rules that should be applicable to any project without any configuration are enabled in this plan.

The free Starter plan includes all other rules, except for those reserved for the paid Essential and Professional plans.

To enable, disable and configure rules you need to create a dbLinter account. Visit the dbLinter Web-GUI click on Sign in and then on Sign up and follow the instructions.

RuleAnonymousStarterEssentialProfessional
G-1010: Try to label your sub blocks.-yesyesyes
G-1020: Always have a matching loop or block label.-yesyesyes
G-1030: Avoid defining variables that are not used.yesyesyesyes
G-1040: Avoid dead code.yesyesyesyes
G-1050: Avoid using literals in your code.-yesyesyes
G-1060: Avoid storing ROWIDs or UROWIDs in database tables.yesyesyesyes
G-1070: Avoid nesting comment blocks.-yesyesyes
G-1080: Avoid using the same expression on both sides of a relational comparison operator or a logical operator.yesyesyesyes
G-1110: Avoid connect users that own database objects.-yesyesyes
G-1120: Avoid granting system privileges to connect users.-yesyesyes
G-1130: Avoid granting table access to API roles.-yesyesyes
G-1140: Avoid granting object privileges directly to connect users.-yesyesyes
G-1150: Always limit privileges of schema owners according to principle of least privileges.-yesyesyes
G-1210: Never create a table without a primary key.-yesyesyes
G-1220: Avoid composite primary keys.-yesyesyes
G-1230: Avoid tables without relationships.-yesyesyes
G-1240: Try to index foreign key columns.-yesyesyes
G-1250: Try to define a business key for each table.-yesyesyes
G-1260: Try to define a comment for each table.-yesyesyes
G-1270: Try to define a comment for each column.-yesyesyes
G-1280: Try to use domains instead of raw datatypes for table columns.-yesyesyes
G-1310: Never keep database objects in an invalid state.-yesyesyes
G-1910: Avoid using the NOSONAR marker.-yesyesyes
G-1920: Avoid syntax errors.yesyesyesyes
G-1930: Avoid long parsing times.-yesyesyes
G-1940: Avoid long checking times.-yesyesyes
G-2110: Try to use anchored declarations for variables, constants and types.-yesyesyes
G-2120: Try to have a single location to define your types.-yesyesyes
G-2130: Try to use subtypes for constructs used often in your code. -yesyesyes
G-2135: Avoid assigning values to local variables that are not used by a subsequent statement.yesyesyesyes
G-2140: Never initialize variables with NULL.yesyesyesyes
G-2145: Never self-assign a variable.yesyesyesyes
G-2150: Avoid comparisons with NULL value, consider using IS [NOT] NULL.yesyesyesyes
G-2160: Avoid initializing variables using functions in the declaration section.-yesyesyes
G-2170: Never overload variables.yesyesyesyes
G-2180: Never use quoted identifiers.yesyesyesyes
G-2185: Avoid using overly short names for explicitly or implicitly declared identifiers. -yesyesyes
G-2190: Avoid using ROWID or UROWID. yesyesyesyes
G-2210: Avoid declaring NUMBER variables, constants or subtypes with no precision.yesyesyesyes
G-2220: Try to use PLS_INTEGER instead of NUMBER for arithmetic operations with integer values. yesyesyesyes
G-2230: Try to use SIMPLE_INTEGER datatype when appropriate. yesyesyesyes
G-2310: Avoid using CHAR data type.yesyesyesyes
G-2320: Never use VARCHAR data type.yesyesyesyes
G-2330: Never use zero-length strings to substitute NULL.yesyesyesyes
G-2340: Always define your VARCHAR2 variables using CHAR SEMANTIC (if not defined anchored).yesyesyesyes
G-2410: Try to use boolean data type for values with dual meaning.-yesyesyes
G-2510: Avoid using the LONG and LONG RAW data types.yesyesyesyes
G-2610: Never use self-defined weak ref cursor types.yesyesyesyes
G-3110: Always specify the target columns when coding an insert statement.yesyesyesyes
G-3115: Avoid self-assigning a column.yesyesyesyes
G-3120: Always use table aliases when your SQL statement involves more than one source.yesyesyesyes
G-3130: Try to use ANSI SQL-92 join syntax.-yesyesyes
G-3140: Try to use anchored records as targets for your cursors. -yesyesyes
G-3145: Avoid using SELECT * directly from a table or view.yesyesyesyes
G-3150: Try to use identity columns for surrogate keys.-yesyesyes
G-3160: Avoid visible virtual columns.-yesyesyes
G-3170: Always use DEFAULT ON NULL declarations to assign default values to table columns if you refuse to store NULL values.(preview)(preview)yesyes
G-3180: Always specify column names instead of positional references in ORDER BY clauses.yesyesyesyes
G-3182: Always specify column names/aliases instead of positional references in GROUP BY clauses.yesyesyesyes
G-3183: Always specify column aliases instead of expressions in GROUP BY clauses.-yesyesyes
G-3185: Never use ROWNUM at the same query level as ORDER BY.yesyesyesyes
G-3190: Avoid using NATURAL JOIN.yesyesyesyes
G-3195: Always use wildcards in a LIKE clause.yesyesyesyes
G-3210: Always use BULK OPERATIONS (BULK COLLECT, FORALL) whenever you have to execute a DML statement for more than 4 times.-yesyesyes
G-3220: Always process saved exceptions from a FORALL statement.yesyesyesyes
G-3310: Never commit within a cursor loop.yesyesyesyes
G-3320: Try to move transactions within a non-cursor loop into procedures.-yesyesyes
G-3330: Avoid autonomous transactions.(preview)(preview)yesyes
G-4110: Always use %NOTFOUND instead of NOT %FOUND to check whether a cursor returned data.-yesyesyes
G-4120: Avoid using %NOTFOUND directly after the FETCH when working with BULK OPERATIONS and LIMIT clause. (preview)(preview)yesyes
G-4130: Always close locally opened cursors.yesyesyesyes
G-4140: Avoid executing any statements between a SQL operation and the usage of an implicit cursor attribute.(preview)(preview)yesyes
G-4210: Try to use CASE rather than an IF statement with multiple ELSIF paths.-yesyesyes
G-4220: Try to use CASE rather than DECODE.-yesyesyes
G-4230: Always use a COALESCE instead of a NVL command, if parameter 2 of the NVL function is a function call or a SELECT statement.yesyesyesyes
G-4240: Always use a CASE instead of a NVL2 command if parameter 2 or 3 of NVL2 is either a function call or a SELECT statement.(preview)(preview)yesyes
G-4250: Avoid using identical conditions in different branches of the same IF or CASE statement.yesyesyesyes
G-4260: Avoid inverting boolean conditions with NOT.-yesyesyes
G-4270: Avoid comparing boolean values to boolean literals.-yesyesyes
G-4310: Never use GOTO statements in your code.yesyesyesyes
G-4320: Always label your loops.-yesyesyes
G-4325: Never reuse labels in inner scope.yesyesyesyes
G-4330: Always use a CURSOR FOR loop to process the complete cursor results unless you are using bulk operations.-yesyesyes
G-4340: Always use a NUMERIC FOR loop to process a dense array.-yesyesyes
G-4350: Always use 1 as lower and COUNT() as upper bound when looping through a dense array. (preview)(preview)yesyes
G-4360: Always use a WHILE loop to process a loose array.yesyesyesyes
G-4365: Never use unconditional CONTINUE or EXIT in a loop.-yesyesyes
G-4370: Avoid using EXIT to stop loop processing unless you are in a basic loop.-yesyesyes
G-4375: Always use EXIT WHEN instead of an IF statement to exit from a loop. -yesyesyes
G-4380: Try to label your EXIT WHEN statements.-yesyesyes
G-4385: Never use a cursor for loop to check whether a cursor returns data.(preview)(preview)yesyes
G-4387: Never use a FOR LOOP for a query that should return not more than one row.(preview)(preview)yesyes
G-4390: Avoid use of unreferenced FOR loop indexes.-yesyesyes
G-4395: Avoid hard-coded upper or lower bound values with FOR loops.-yesyesyes
G-5010: Try to use a error/logging framework for your application.-yesyesyes
G-5020: Never handle unnamed exceptions using the error number.(preview)(preview)yesyes
G-5030: Never assign predefined exception names to user defined exceptions.yesyesyesyes
G-5040: Avoid use of WHEN OTHERS clause in an exception section without any other specific handlers.-yesyesyes
G-5050: Avoid use of the RAISE_APPLICATION_ERROR built-in procedure with a hard-coded 20nnn error number or hard-coded message. -yesyesyes
G-5060: Avoid unhandled exceptions.-yesyesyes
G-5070: Avoid using Oracle predefined exceptions.yesyesyesyes
G-5080: Always use FORMAT_ERROR_BACKTRACE when using FORMAT_ERROR_STACK or SQLERRM.yesyesyesyes
G-6010: Always use a character variable to execute dynamic SQL.-yesyesyes
G-6020: Try to use output bind arguments in the RETURNING INTO clause of dynamic DML statements rather than the USING clause. -yesyesyes
G-7110: Try to use named notation when calling program units.-yesyesyes
G-7120: Always add the name of the program unit to its end keyword.-yesyesyes
G-7125: Always use CREATE OR REPLACE instead of CREATE alone.-yesyesyes
G-7130: Always use parameters or pull in definitions rather than referencing external variables in a local program unit.-yesyesyes
G-7140: Always ensure that locally defined procedures or functions are referenced.yesyesyesyes
G-7150: Try to remove unused parameters.-yesyesyes
G-7160: Always explicitly state parameter mode.-yesyesyes
G-7170: Avoid using an IN OUT parameter as IN or OUT only.-yesyesyes
G-7180: Try to keep the complexity of functions, procedures and triggers simple.-yesyesyes
G-7210: Try to keep your packages small. Include only few procedures and functions that are used in the same context.-yesyesyes
G-7220: Always use forward declaration for private functions and procedures.-yesyesyes
G-7230: Avoid declaring global variables public.yesyesyesyes
G-7250: Never use RETURN in package initialization block.-yesyesyes
G-7310: Avoid standalone procedures – put your procedures in packages.-yesyesyes
G-7320: Avoid using RETURN statements in a PROCEDURE.-yesyesyes
G-7330: Always assign values to OUT parameters.yesyesyesyes
G-7410: Avoid standalone functions – put your functions in packages.-yesyesyes
G-7420: Always make the RETURN statement the last statement of your function.-yesyesyes
G-7430: Try to use no more than one RETURN statement within a function.-yesyesyes
G-7440: Never use OUT parameters to return values from a function.-yesyesyes
G-7450: Never return a NULL value from a BOOLEAN function.(preview)(preview)yesyes
G-7460: Try to define your packaged/standalone function deterministic if appropriate.-yesyesyes
G-7510: Always prefix Oracle supplied packages with owner schema name.-(preview)yesyes
G-7520: Avoid using deprecated units in your own code.-yesyesyes
G-7710: Avoid cascading triggers.-yesyesyes
G-7720: Never use multiple UPDATE OF in trigger event clause.yesyesyesyes
G-7730: Avoid multiple DML events per trigger.-yesyesyes
G-7740: Never handle multiple DML events per trigger if primary key is assigned in trigger.-(preview)yesyes
G-7810: Never use SQL inside PL/SQL to read sequence numbers (or SYSDATE).yesyesyesyes
G-7910: Never use DML within a SQL macro.(preview)(preview)yesyes
G-8110: Never use SELECT COUNT(*) if you are only interested in the existence of a row.(preview)(preview)yesyes
G-8120: Never check existence of a row to decide whether to create it or not.(preview)(preview)yesyes
G-8210: Always use synonyms when accessing objects of another application schema.-yesyesyes
G-8310: Always validate input parameter size by assigning the parameter to a size limited variable in the declaration section of program unit.-yesyesyes
G-8410: Always use application locks to ensure a program unit is only running once at a given time.-yesyesyes
G-8510: Always use dbms_application_info to track program process transiently.-yesyesyes
G-9010: Always use a format model in string to date/time conversion functions.yesyesyesyes
G-9020: Try to use a format model and NLS_NUMERIC_CHARACTERS in string to number conversion functions.-yesyesyes
G-9030: Try to define a default value on conversion errors.-yesyesyes
G-9040: Try using FX in string to date/time conversion format model to avoid fuzzy conversion.(preview)(preview)yesyes
G-9101: Always follow naming conventions for global variables.-yesyesyes
G-9102: Always follow naming conventions for local variables.-yesyesyes
G-9103: Always follow naming conventions for cursor variables.-yesyesyes
G-9104: Always follow naming conventions for record variables.-yesyesyes
G-9105: Always follow naming conventions for collection variables (arrays/tables).-yesyesyes
G-9106: Always follow naming conventions for object variables.-yesyesyes
G-9107: Always follow naming conventions for cursor parameters.-yesyesyes
G-9108: Always follow naming conventions for IN parameters of functions and procedures.-yesyesyes
G-9109: Always follow naming conventions for OUT parameters of functions and procedures.-yesyesyes
G-9110: Always follow naming conventions for IN/OUT parameters of functions and procedures.-yesyesyes
G-9111: Always follow naming conventions for record type definitions.-yesyesyes
G-9112: Always follow naming conventions for collection type definitions (arrays/tables).-yesyesyes
G-9113: Always follow naming conventions for exceptions.-yesyesyes
G-9114: Always follow naming conventions for constants.-yesyesyes
G-9115: Always follow naming conventions for subtypes.-yesyesyes
G-9116: Always follow naming conventions for record fields.-yesyesyes
G-9201: Always follow naming conventions for tables.-yesyesyes
G-9202: Always follow naming conventions for table/view columns.-yesyesyes
G-9203: Always follow naming conventions for indexes.-yesyesyes
G-9204: Always follow naming conventions for primary key constraints.-yesyesyes
G-9205: Always follow naming conventions for unique constraints.-yesyesyes
G-9206: Always follow naming conventions for foreign key constraints.-yesyesyes
G-9207: Always follow naming conventions for check constraints.-yesyesyes
G-9208: Always follow naming conventions for assertions.-yesyesyes
G-9209: Always follow naming conventions for global temporary tables.-yesyesyes
G-9210: Always follow naming conventions for views.-yesyesyes
G-9211: Always follow naming conventions for sequences.-yesyesyes
G-9212: Always follow naming conventions for synonyms.-yesyesyes
G-9213: Always follow naming conventions for triggers.-yesyesyes
G-9214: Always follow naming conventions for PL/SQL packages.-yesyesyes
G-9215: Always follow naming conventions for functions.-yesyesyes
G-9216: Always follow naming conventions for procedures.-yesyesyes
G-9217: Always follow naming conventions for object types.-yesyesyes
G-9218: Always follow naming conventions for object type attributes.-yesyesyes
G-9219: Always follow naming conventions for collection types.-yesyesyes
G-9501: Never use parameter in string expression of dynamic SQL. Use asserted local variable instead.(preview)(preview)yesyes
G-9600: Never define more than one comment with hints.(preview)(preview)yesyes
G-9601: Never use unknown hints.yesyesyesyes
G-9602: Always use the alias name instead of the table name.(preview)(preview)yesyes
G-9603: Never reference an unknown table/alias.(preview)(preview)yesyes
G-9604: Never use an invalid stats method.(preview)(preview)yesyes
G-9605: Never use an invalid stats keyword.(preview)(preview)yesyes

The rules marked with (preview) for the Anonymous and Starter plans are only available during the preview phase.