> ## Documentation Index
> Fetch the complete documentation index at: https://docs.erlc.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Persistent Database Storage Blocks in erlc.dev Studio

> Store and retrieve persistent data across automation runs using erlc.dev Studio's named database sets, each holding up to 100 string slots.

The erlc.dev Studio database gives your automations a place to store values that survive between runs. Unlike in-run list or variable blocks, database data persists on the server until you explicitly delete it — making it ideal for player flags, cooldown timestamps, whitelists, and any other state that needs to outlast a single event.

***

## Data Model

<CardGroup cols={2}>
  <Card title="Sets" icon="table-cells">
    A **set** is a named collection identified by a string (for example `"banned_players"` or `"cooldowns"`). Think of it as a named array or a single-column table. You can have as many sets as you need.
  </Card>

  <Card title="Slots" icon="hashtag">
    Each set has up to **100 slots** numbered 1–100. Every slot holds one string value. Slots not yet written return an empty value.
  </Card>
</CardGroup>

Key properties of the database:

* Values are stored and returned as **strings**.
* Sets **persist across automation runs** until you delete them with `erlc_database_delete_set`.
* Sets are **server-scoped** — all automations on your server share the same database.
* Use `erlc_database_find` to locate a value by content (returns its slot position, or `0` if absent).

**Common use cases:**

* Store a whitelist of permitted player IDs in a set called `"whitelist"`.
* Track per-player cooldown expiry times in a set called `"cooldowns"`.
* Record server-state flags (e.g. lockdown active) in a single-slot set.
* Maintain a ban list that persists after server restarts.

***

## Reading Data

<CardGroup cols={2}>
  <Card title="erlc_database_read" icon="book-open">
    Returns the string value stored at `POSITION` (1–100) in the set named by the `SET` input. Returns an empty value if the slot has not been written.
  </Card>

  <Card title="erlc_database_find" icon="magnifying-glass">
    Searches the set named by `SET` for the string in `VALUE`. Returns the 1-based slot position of the first match, or `0` if the value is not found.
  </Card>

  <Card title="erlc_database_search" icon="magnifying-glass-plus">
    Searches **all sets** for the value provided in `VALUE`. Returns the position of the first match found across any set.
  </Card>

  <Card title="erlc_database_set" icon="table-list">
    Returns data from the set named by the `SET` input. The `SELECTION` field controls what is returned: `values` (all stored strings), `positions` (all occupied slot numbers), or `records` (slot/value pairs).
  </Card>

  <Card title="erlc_database_slot" icon="location-dot">
    A value block that produces a slot number. Set the `POSITION` field (1–100). Use this anywhere a slot number input is required for clarity instead of a raw number literal.
  </Card>
</CardGroup>

***

## Writing Data

<CardGroup cols={2}>
  <Card title="erlc_database_write_value" icon="pen-to-square">
    Writes the string in `VALUE` to the slot at `POSITION` within the set named by `SET`. Overwrites any existing value in that slot.
  </Card>

  <Card title="erlc_database_write_set" icon="floppy-disk">
    Replaces the **entire contents** of the set named by `SET` with the list provided in the `VALUES` input. The first list item goes to slot 1, the second to slot 2, and so on (up to 100).
  </Card>
</CardGroup>

<Warning>
  `erlc_database_write_set` overwrites every slot in the target set. Any values previously stored in slots beyond the length of your new list will be cleared. Use `erlc_database_write_value` when you only need to update a single slot.
</Warning>

***

## Deleting Data

<CardGroup cols={1}>
  <Card title="erlc_database_delete_set" icon="trash">
    Permanently deletes the entire set named by the `SET` input, including all of its slot values. This action cannot be undone.
  </Card>
</CardGroup>

***

## JSON Examples

### Writing a Value and Reading It Back

The example below writes the string `"active"` to slot `1` of a set called `"server_state"`, then reads it back in a subsequent block.

```json theme={null}
{
  "type": "erlc_database_write_value",
  "id": "block_write_1",
  "inputs": {
    "VALUE": {
      "block": {
        "type": "erlc_text_value",
        "id": "block_val_1",
        "fields": { "VALUE": "active" }
      }
    },
    "SET": {
      "block": {
        "type": "erlc_text_value",
        "id": "block_set_1",
        "fields": { "VALUE": "server_state" }
      }
    },
    "POSITION": {
      "block": {
        "type": "erlc_database_slot",
        "id": "block_slot_1",
        "fields": { "POSITION": "1" }
      }
    }
  },
  "next": {
    "block": {
      "type": "erlc_database_read",
      "id": "block_read_1",
      "inputs": {
        "POSITION": {
          "block": {
            "type": "erlc_database_slot",
            "id": "block_slot_2",
            "fields": { "POSITION": "1" }
          }
        },
        "SET": {
          "block": {
            "type": "erlc_text_value",
            "id": "block_set_2",
            "fields": { "VALUE": "server_state" }
          }
        }
      }
    }
  }
}
```

### Checking Whether a Player ID Exists in a Set

Use `erlc_database_find` to check for a player ID in a `"whitelist"` set. A return value greater than `0` means the player was found.

```json theme={null}
{
  "type": "erlc_if_else",
  "id": "block_if_1",
  "inputs": {
    "CONDITION": {
      "block": {
        "type": "erlc_compare_values",
        "id": "block_cmp_1",
        "fields": { "OPERATOR": ">" },
        "inputs": {
          "LEFT": {
            "block": {
              "type": "erlc_database_find",
              "id": "block_find_1",
              "inputs": {
                "VALUE": {
                  "block": {
                    "type": "erlc_text_value",
                    "id": "block_pid_1",
                    "fields": { "VALUE": "12345678" }
                  }
                },
                "SET": {
                  "block": {
                    "type": "erlc_text_value",
                    "id": "block_set_3",
                    "fields": { "VALUE": "whitelist" }
                  }
                }
              }
            }
          },
          "RIGHT": {
            "block": {
              "type": "erlc_number_value",
              "id": "block_num_0",
              "fields": { "VALUE": 0 }
            }
          }
        }
      }
    },
    "THEN": {
      "block": {
        "type": "erlc_bot_send_message",
        "id": "block_allow_1"
      }
    },
    "ELSE": {
      "block": {
        "type": "erlc_bot_send_message",
        "id": "block_deny_1"
      }
    }
  }
}
```

<Tip>
  Store player IDs as strings in consecutive slots starting at slot 1, and use `erlc_database_find` to check membership in O(n) time. For sets that grow beyond a few dozen entries, prefer `erlc_database_write_set` to bulk-load the entire list in one operation rather than writing slot by slot.
</Tip>

<Info>
  `erlc_database_set` with `SELECTION` set to `values` returns all stored strings in the set as a list, which you can then pass directly to an `erlc_for_each` block to iterate over every entry.
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.