2010-01-15 3 views
2

MySQL Connector/Net을 사용하고 있으며 런타임에 이름이 지정 될 테이블에 대해 쿼리를 작성하려고합니다. 난 당신이 쿼리에서 테이블 이름을 매개 변수화 할 수 있다고 생각하지 않기 때문에, 오히려 문자열보다 열거를 사용런타임시 테이블 이름을 동적으로 선택하는 가장 좋은 방법은 무엇입니까?

public class DataAccess 
{ 
    public enum LookupTable 
    { 
     Table1, 
     Table2, 
     Table3 
    } 

    public int GetLookupTableRowCount(LookupTable table) 
    { 
     string tableName = string.Empty; 

     switch (table) 
     { 
      case LookupTable.Table1: 
       tableName = "table_1"; 
       break; 
      case LookupTable.Table2: 
       tableName = "table_2"; 
       break; 
      case LookupTable.Table3: 
       tableName = "table_3"; 
       break; 
      default: 
       throw new ApplicationException("Invalid lookup table specified."); 
     } 

     string commandText = string.Concat("SELECT COUNT(*) FROM ", tableName); 

    // Query gets executed and function returns a value here... 
    } 
} 

:

이 예는 (안 테스트) 내 머리 위로 떨어져이다 함수 매개 변수는 SQL injection의 가능성을 제한합니다.

좋은 접근 방법 인 것 같습니까? 더 좋은 방법이 있습니까?

+0

.net은 열거 형에 추가 속성을 추가 할 수 있습니까? – Jherico

+0

Table1 = "table_1"과 같은 의미입니까? 그렇다면 int, long과 같은 정수 유형 만 사용할 수 있습니다. –

답변

4

MySQL에서 identifier (테이블 이름 또는 필드 이름)을 매개 변수화 할 수는 없지만 역 슬금을 사용하여 이스케이프 할 수 있습니다.

다음 쿼리는 안전하게 실행되지만 테이블이 존재하지 않기 때문에 (몇 가지 이상한 우연히 실제로 같은 이름의 테이블이없는 경우) 오류가 발생합니다 : 기본적으로

SELECT * FROM `users; DROP TABLE users;`; 

을, 동적 사용할 수 있습니다 이름 또는 필드는 백틱으로 묶어야합니다.

tableName = tableName.Replace("`", ""); 
string commandText = "SELECT COUNT(*) FROM `" + tableName + "`"; 
+0

나는 당신이 말하는 것을보고 있지만, 자유로운 양식 입력으로부터 쿼리 텍스트를 분리하는 것이 더 안전하다고 생각합니다. 그래서 데이터 액세스 방법에 문자열 매개 변수를 사용하고 싶지 않습니다. –

+0

음, 언어의 의미를 믿을 수는 없습니다. MySQL의 백틱 및 이스케이프 메소드를 신뢰하거나 그렇지 않습니다.다른 방법으로 제안한 것과 같이 일종의 조회 테이블을 통해 데이터베이스 구조를 코드에 연결하는 방법이 있습니다. 개인적으로 매우 불쾌한 점이 있습니다. – zombat

+0

실제로 유효 식별자가 무엇인지에 대한 정보를 제공하므로 실제로 해당 식별자를 철저히 읽으라고 제안합니다. 추가 보호 기능을 원한다면 영숫자 문자 만 적용하거나 심지어 테이블이 미리 존재하는지 확인하기 위해 쿼리 할 수 ​​있습니다. 그러나 MySQL은 쿼리에 오류를 발생시켜 식별자의 잘못된 문자를 처리합니다. – zombat

1

오른쪽으로, 테이블 이름, 열 이름, SQL 키워드 또는 식 등에 대해 쿼리 매개 변수를 사용할 수 없습니다. 단일 값에 대해서만 쿼리 매개 변수를 사용할 수 있습니다.

입력으로부터 리터럴 테이블 이름으로의 일종의 매핑을 수행하는 것이 SQL 주입으로부터 보호하는 좋은 방법이라는 데 동의합니다.

저는 .NET에서 프로그래밍하지 않습니다. 보통 PHP, Python 또는 Perl과 같은 동적 언어를 사용합니다. 그래서 해시 배열을 사용합니다. 열거 변수를 사용하여 해시 배열에 색인을 지정하기 만하면 switch()을 건너 뛸 수 있습니다.

$tableName = $tableNameHash[ $table ]; 

.NET은 데이터 구조의 해시 맵 유형을 지원합니까? 그게 제가 찾던 것입니다.


표준 C++ 라이브러리에는 hash_map 클래스가있는 것처럼 보입니다.

+0

예, .NET에는 해시 테이블과 사전 및 기타 많은 컬렉션 스타일 클래스가 있습니다. 나는 너의 제안을 좋아한다. –

2

동적 테이블 이름이 좋은 방법 결코 (당신이 유사한 PHPMyAdmin 또는 무언가를 개발하지 않는 한) :이 방법은 SQL 주입을 방지하기 위해, 당신이해야 할 첫 번째 어떤 역 따옴표를 제거합니다.

테이블 이름이 제한되어 있으면 저장 프로 시저를 만들고 매개 변수로 호출하면 어떨까요?

DECLARE _which INT 
BEGIN 
     SELECT COUNT(*) 
     FROM table_1 
     WHERE _which = 1 
     UNION ALL 
     SELECT COUNT(*) 
     FROM table_2 
     WHERE _which = 2 
     UNION ALL 
     SELECT COUNT(*) 
     FROM table_3 
     WHERE _which = 3 
END 
+3

나는 결코 좋은 접근 방식에 동의하지 않습니다. 대기업 응용 프로그램은 일종의 동적 명명 체계를 사용하여 데이터를 관리 가능한 집합으로 분리합니다. 데이터베이스 샤딩 기법은 테이블뿐만 아니라 동적 * 데이터베이스 * 이름을 사용합니다. – zombat