v.db.select(1grass)

πŸ’– v.db.select πŸ’–

okay bestie, welcome to part 1 of the v.db.select page from the GRASS User's Manual β€” this is the one that prints your vector map attributes and honestly? she does a lot. let's get into it 🫢

🌈 NAME 🌈

v.db.select β€” Prints vector map attributes.

✨ KEYWORDS ✨

vector, attribute table, database, SQL, export


πŸŽ€ SYNOPSIS πŸŽ€

v.db.select
v.db.select --help
v.db.select [-rcef] map=name  [layer=string]   [columns=name[,name,...]]
[where=sql_query]   [group=string]  format=name  [separator=character]
[vertical_separator=character]   [null_value=string]   [file=name]
[--overwrite]  [--help]  [--verbose]  [--quiet]  [--ui]

🚩 Flags 🚩

  • -r β€” instead of dumping attributes, print the minimal region extent of the selected vector features. giving map-bounds energy πŸ“
  • -c β€” do NOT put column names in the output. just the data, no header, no intro. mysterious πŸ’…
  • -e β€” escape newline and backslash characters. lowkey essential if a computer is gonna read this.
  • -f β€” exclude attributes that aren't linked to features.
  • --overwrite β€” let output files overwrite files that already exist. permission to be a little destructive πŸ”₯
  • --help β€” print the usage summary.
  • --verbose β€” verbose module output. she talks more.
  • --quiet β€” quiet module output. she talks less.
  • --ui β€” force launching the GUI dialog. clicking instead of typing, valid.

🧚 Parameters 🧚

  • map=name [required] β€” Name of vector map. Or, plot twist, a data source for direct OGR access.
  • layer=string β€” Layer number or name. Vector features can have category values in different layers, and this number decides which layer gets used. When you're doing direct OGR access, this is the layer name instead. Default: 1.
  • columns=name[,name,...] β€” Name of attribute column(s). plural bestie, go wild.
  • where=sql_query β€” WHERE conditions of an SQL statement, without the where keyword. Example: income < 1000 and population >= 10000.
  • group=string β€” GROUP BY conditions of an SQL statement, without the group by keyword.
  • format=name [required] β€” Output format. Options: plain, csv, json, vertical Default: plain
    • plain: Configurable plain text output
    • csv: CSV (Comma Separated Values)
    • json: JSON (JavaScript Object Notation)
    • vertical: Plain text vertical output (instead of horizontal)
  • separator=character β€” Field separator. Special characters: pipe, comma, space, tab, newline.
  • vertical_separator=character β€” Output vertical record separator. Special characters: pipe, comma, space, tab, newline.
  • null_value=string β€” String representing NULL value.
  • file=name β€” Name for output file (if it's omitted or it's -, output goes to stdout).

🌸 DESCRIPTION 🌸

v.db.select prints attributes of a vector map, pulled from one or several attribute table columns that you selected. main character energy, you're choosing 🫢

πŸ“ Output formats πŸ“

Four different formats can be used depending on the circumstances, and you pick with the format option: plain text, CSV, JSON, and vertical plain text.

πŸ“ Plain text πŸ“

Plain text is the default output and it's the one most suitable for humans reading it β€” like when you're chilling in the command line, or grabbing specific values out of the attribute table using the v.db.select GUI dialog.

The individual fields (attribute values) are separated by a pipe (|), and you can customize that with the separator option. The records (rows) are separated by newlines.

Example with a pipe as a separator (the default):

cat|road_name|multilane|year|length
1|NC-50|no|2001|4825.369405
2|NC-50|no|2002|14392.589058
3|NC-98|no|2003|3212.981242
4|NC-50|no|2004|13391.907552

When escaping is enabled, the following characters in the fields are escaped: backslash (\\), carriage return (\r), line feed (\n), tabulator (\t), form feed (\f), and backslash (\b).

No quoting or escaping is performed by default, so if these characters are in the output, they look just like the separators. This is usually not a problem for humans looking at the output to get a general idea about query result or attribute table content.

Consequently, this format is not recommended for computers, e.g., for reading attribute data in Python scripts. It works for further parsing in limited cases when the values don't contain separators or when the separators are set to one of the escaped characters. 😭

πŸ’… CSV πŸ’…

CSV (comma-separated values) has many variations, it's giving chaotic. This module by default produces CSV with comma (,) as the field separator (delimiter). All text fields (based on the type) are quoted with double quotes. Double quotes in fields are represented as two double quotes. Newline characters in the fields are present as-is in the output. Header is included by default containing column names.

All full CSV parsers such as the ones in LibreOffice or Python are able to parse this format when configured to the above specification. slay.

Example with default settings:

cat,road_name,multilane,year,length
1,"NC-50","no",2001,4825.369405
2,"NC-50","no",2002,14392.589058
3,"NC-98","no",2003,3212.981242
4,"NC-50","no",2004,13391.907552

If desired, the separator can be customized and escaping can be enabled with the same characters being escaped as for the plain text. Notably, newlines and tabs are escaped, double quotes are not, and the separator is not escaped either (unless it is a tab). However, the format is guaranteed only for the commonly used separators such as comma, semicolon, pipe, and tab.

Note that using multi-character separator is allowed, but not recommended as it is not generally supported by CSV readers.

CSV is the recommended format for further use in another analytical applications, especially for use with spreadsheet applications. For scripting, it is advantageous when tabular data is needed (rather than key-value pairs). ✨

πŸ¦‹ JSON πŸ¦‹

JSON (JavaScript Object Notation) format is produced according to the specification so it is readily readable by JSON parsers. The standard JSON escapes are performed (backslash, carriage return, line feed, tabulator, form feed, backslash, and double quote) for string values. Numbers in the database such as integers and doubles are represented as numbers, while texts (TEXT, VARCHAR, etc.) and dates in the database are represented as strings in JSON. NULL values in database are represented as JSON null. Indentation and newlines in the output are minimal and not guaranteed.

Records which are the result of the query are stored under key records as an array (list) of objects (collections of key-value pairs). The keys for attributes are lowercase or uppercase depending on how the columns were defined in the database.

The JSON also contains information about columns stored under key info. Column names and types are under key columns. Each column has SQL data type under sql_type in all caps. A boolean is_number specifies whether the value is a number, i.e., integer or floating point number. The is_number value is added for convenience and it is recommended to rely on the types derived from the JSON representation or the SQL types. The definition of is_number may change in the future.

Example with added indentation:

{
  "info": {
    "columns": [
      {
        "name": "road_name",
        "sql_type": "CHARACTER",
        "is_number": false
      },
      {
        "name": "year",
        "sql_type": "INTEGER",
        "is_number": true
      },
      {
        "name": "length",
        "sql_type": "DOUBLE PRECISION",
        "is_number": true
      }
    ]
  },
  "records": [
    {
      "road_name": "NC-50",
      "year": 2001,
      "length": 4825.369405
    },
    {
      "road_name": "NC-50",
      "year": 2001,
      "length": 14392.589058
    }
  ]
}

JSON is the recommended format for reading the data in Python and for any uses and environments where convenient access to individual values is desired and JSON parser is available. 🐍 iconic behaviour

πŸ‘‘ Vertical plain text πŸ‘‘

In the vertical plain text format, each value is on a single line and is preceded by the name of the attribute (column) which is separated by separator. The individual records can be separated by the vertical separator (vertical_separator option).

Example with (horizontal) separator = and vertical separator newline:

cat=1
road_name=NC-50
multilane=no
year=2001
length=4825.369405
cat=2
road_name=NC-50
multilane=no
year=2002
length=14392.589058

Newline is automatically added after a vertical separator unless it is a newline which allows for separating the records, e.g., by multiple dashes. The escaping (-e) need to should be enabled in case the output is meant for reading by a computer rather than just as a data overview for humans. Escaping will ensure that values with newlines will be contained to a single line. This format is for special uses in scripting, for example, in combination with columns option set to one column only and escaping (-e) and no column names flags (-c). It is also advantageous when you need implement the parsing yourself.


⭐ NOTES ⭐

  • CSV and JSON were added in version 8.0 as new primary formats for further consumption by scripts and other applications. no cap, that was a glow up.
  • Escaping of plain and vertical formats was extended from just backslash and newlines to all escapes from JSON except for double quote character.

...okay bestie, that's part 1, and there's more coming so don't go anywhere πŸ’œ

πŸ’– EXAMPLES πŸ’–

Okay bestie, every single one of these is based on the North Carolina sample dataset. Grab a snack, we're going through them all πŸ“


🌈 Select and show entire table

v.db.select map=roadsmajor
cat|MAJORRDS_|ROAD_NAME|MULTILANE|PROPYEAR|OBJECTID|SHAPE_LEN
1|1|NC-50|no|0|1|4825.369405
2|2|NC-50|no|0|2|14392.589058
3|3|NC-98|no|0|3|3212.981242
4|4|NC-50|no|0|4|13391.907552
...

Like, the whole entire table. Every row, every column, no filter, no cap ✨


πŸŽ€ Select and show single column from table

Note: multiple columns can be specified as comma separated list.

iykyk β€” just comma-separate them and you're golden πŸ’…

v.db.select map=roadsmajor column=ROAD_NAME
NC-50
NC-50
NC-98
NC-50
NC-98
...

v.db.select -r map=roadsmajor where="ROAD_NAME = ’NC-98’"
n=248425.389891
s=245640.640081
w=635906.517653
e=661979.801880

Just the bounding box, nothing else. n, s, w, e β€” periodt πŸ‘‘


🌸 Select empty vector features (no data entries)

v.db.select geonames_wake where="ALTERNATEN IS NULL"
cat|GEONAMEID|NAME|ASCIINAME|ALTERNATEN|FEATURECLA|FEATURECOD|...
8|4498303|West Raleigh|West Raleigh||P|PPL|US||NC|338759|123|...
14|4459467|Cary|Cary||P|PPL|US||NC|103945|146|152|America/Iqaluit|...
31|4452808|Apex|Apex||P|PPL|US||NC|30873|167|134|America/Iqaluit|...
...

The IS NULL vibe check: these rows have nothing in that field πŸ™ˆ


🧚 Select not empty vector features (no data entries)

v.db.select geonames_wake where="ALTERNATEN IS NOT NULL"
cat|GEONAMEID|NAME|ASCIINAME|ALTERNATEN|FEATURECLA|FEATURECOD|...
9|4487042|Raleigh|Raleigh|Raleigh,...
31299|4487056|Raleigh-Durham Airport|Raleigh-Durham Airport|...
...

And IS NOT NULL flips it β€” only the rows that do have something. Slay 🌟


πŸ’œ Select features with distinct road names

v.db.select map=roadsmajor columns=ROAD_NAME group=ROAD_NAME
ROAD_NAME
I-40
I-440
I-540
NC-231
NC-39
NC-42
...

It is also possible to combine with where option πŸ’«

v.db.select map=roadsmajor columns=ROAD_NAME,MULTILANE group=ROAD_NAME where=’ROAD_NAME is not null’
ROAD_NAME|MULTILANE
I-40|yes
I-440|yes
I-540|yes
NC-231|no
NC-39|no
NC-42|no
NC-50|no
NC-54|no
NC-55|no
NC-96|no
NC-97|no
NC-98|no
US-1|
US-401|no
US-64|yes
US-70|yes

It can also use more columns in group option β€” yes bestie, it's giving flexible 🫢

v.db.select map=roadsmajor columns=ROAD_NAME,MULTILANE group=ROAD_NAME,MULTILANE where=’ROAD_NAME is not null’
ROAD_NAME|MULTILANE
I-40|yes
I-440|yes
I-540|yes
NC-231|no
NC-39|no
NC-42|no
NC-50|no
NC-54|no
NC-55|no
NC-96|no
NC-97|no
NC-98|no
US-1|
US-1|yes
US-401|no
US-401|yes
US-64|yes
US-70|yes

⭐ Read results in Python

The json package in the standard Python library can load a JSON string obtained as output from the v.db.select module through the read_command function:

import json
import grass.script as gs
text = gs.read_command("v.db.select", map="roadsmajor", format="json")
data = json.loads(text)
for row in data["records"]:
    print(row["ROAD_NAME"])

Not me writing four lines of Python and getting a whole dataframe's worth of vibes. Main character energy fr fr πŸ˜­πŸ’–


πŸ‘€ SEE ALSO πŸ‘€

  • db.select
  • GRASS SQL interface

πŸ‘‘ AUTHORS πŸ‘‘

  • Radim Blazek, ITC-Irst, Trento, Italy
  • Minimal region extent added by Martin Landa, FBK-irst (formerly ITC-irst), Trento, Italy
  • group option added by Luca Delucchi, Fondazione Edmund Mach, Trento, Italy
  • Huidae Cho (JSON output, escaping and features-only flags)
  • Vaclav Petras (true CSV output, format option and documentation)

Absolute legends, every single one 🫢


πŸ’» SOURCE CODE πŸ’»

Available at: v.db.select source code (history)

Latest change: Thursday Nov 06 22:27:54 2025 in commit:

298b38614712934179355ea767403d6bfea8f5f9

Main index | Vector index | Topics index | Keywords index | Graphical index | Full index

Β© 2003-2026 GRASS Development Team, GRASS 8.5.0 Reference Manual


and that's a wrap bestie πŸŽ€ this was v.db.select(1grass) from the GRASS 8.5.0 reference manual, last touched all the way back on Thursday Nov 06 22:27:54 2025. go forth and query something iconic βœ¨πŸ’…

πŸ“¦ where this page comes from