# Opsdeck Normalization Checker (keys, minimal cover, 2NF/3NF/BCNF, decomposition) > Candidate keys, minimal cover, 2NF/3NF/BCNF and lossless decompositions from FDs. Enter a relation and its functional dependencies (or paste sample rows and let the tool propose dependencies as hypotheses with support counts). You get attribute closures, all candidate keys, prime attributes, a minimal cover, the highest normal form with every violating dependency explained, a 3NF synthesis (Bernstein: lossless and dependency preserving) and a BCNF decomposition, each with the chase test for lossless joins and the dependency-preservation test. Any decomposition of your own can be tested too. Part of usefulweb.site (https://usefulweb.site/). Part of [Opsdeck](https://opsdeck.usefulweb.site/) (ownerApp: opsdeck). Results are deterministic calculations from the inputs and the listed assumptions; the API returns exactly what the web page shows. ## Use it - Human interface: https://opsdecknormalizationchecker.usefulweb.site/ (interactive tool at https://opsdecknormalizationchecker.usefulweb.site/tool) - JSON API: POST https://opsdecknormalizationchecker.usefulweb.site/api/v1/calculate with a JSON object of inputs (schema: https://opsdecknormalizationchecker.usefulweb.site/api/v1/tool) - OpenAPI: https://opsdecknormalizationchecker.usefulweb.site/openapi.json - MCP (Streamable HTTP): https://opsdecknormalizationchecker.usefulweb.site/mcp - tool `opsdeck_normalization_checker` ## Inputs - relation (text): Relation - Name and attributes. Leave empty to take the attributes from the header of the sample rows. - fds (textarea): Functional dependencies (one per line) - Write A, B -> C, D. With one-letter attributes AB -> C works too. - decomposition (textarea): Decomposition to test (optional) - One relation per line; the tool runs the chase test and the dependency-preservation test on it. - sampleCsv (textarea): Sample rows (CSV with header, optional) - Dependencies that hold in every row are proposed as hypotheses with support counts. A sample can only refute a dependency, never prove it. - maxLhs (integer): Largest left side to search in the sample - useMinedFds (boolean): Use the dependencies found in the sample for the analysis ## Method - Attribute closure X+ is computed by applying the dependencies until nothing changes. Attributes that never appear on a right side are in every key; the remaining candidates are searched by increasing size, skipping supersets of keys already found. - Minimal (canonical) cover: right sides split into single attributes, extraneous left-side attributes removed, redundant dependencies removed (Silberschatz et al., section 7.4.3). - Normal forms (first normal form is assumed): 2NF fails when a non-prime attribute depends on part of a candidate key; 3NF fails when X → A has X not a superkey and A non-prime; BCNF fails when X → A has X not a superkey. Checking the given dependencies suffices for 3NF and BCNF of the relation itself; parts of a decomposition use the dependencies projected onto them. - 3NF synthesis (Bernstein): one relation per left side of the minimal cover, plus a candidate key if no relation contains one; relations contained in others are removed. BCNF decomposition splits on a violating X → Y into X+ and R − (X+ − X) until every part is in BCNF. - Lossless join: the chase (tableau) test. Dependency preservation: each dependency of the cover is checked by growing the closure of its left side through the parts only (Ullman’s algorithm, no projection needed). - Sample rows: every left side of up to three attributes is checked against every other attribute; only minimal dependencies that hold in all rows are proposed, with the number of row groups that share the left side as support. Unique attribute sets are listed as key hypotheses.