Hay dos enfoques. Una es componer una sola expresión que maneje todas las alternativas posibles:
^[a-zA-Z][0-9][a-zA-Z0-9-,._;:]{6,}$
|
^[a-zA-Z][a-zA-Z0-9-,._;:][0-9][a-zA-Z0-9-,._;:]{5,}$
|
^[a-zA-Z][a-zA-Z0-9-,._;:]{2}[0-9][a-zA-Z0-9-,._;:]{4,}$
etc. Esta es una pesadilla combinatoria, pero funcionaría.
Un enfoque mucho más simple es validar la misma cadena dos veces usando dos expresiones:
^[a-zA-Z0-9-,._;:]{8,}$ # check length and permitted characters
y
[a-zA-Z].*[0-9]|[0-9].*[a-zA-Z] # check required characters
EDITAR:@briandfoy señala correctamente que será más eficiente buscar cada carácter requerido por separado:
[a-zA-Z] # check for required alpha
y
[0-9] # check for required digit