복붙노트

[SQL] 왜 우리는 항상 SQL 문에서 매개 변수를 사용하여 선호합니까?

SQL

왜 우리는 항상 SQL 문에서 매개 변수를 사용하여 선호합니까?

나는 데이터베이스 작업에 아주 새로운 오전. 지금은 SELECT, UPDATE, DELETE 및 INSERT 명령을 작성할 수 있습니다. 그러나 나는 우리가 쓰기에 선호하는 많은 포럼을 보았다 :

SELECT empSalary from employee where salary = @salary

...대신에:

SELECT empSalary from employee where salary = txtSalary.Text

왜 우리는 항상 매개 변수를 사용하는 것을 선호합니까이며 어떻게 사용해야합니까?

나는 첫 번째 방법의 사용과 장점을 알고 싶었다. 난 SQL 주입 들었하지만 난 그것을 완전히 이해하지 않습니다. SQL 주입은 내 질문에 관련이 있는지 나는 알지도하지 않습니다.

해결법

  1. ==============================

    1.데이터베이스는 데스크탑 프로그램이나 웹 사이트 등의 프로그램 인터페이스와 함께 사용 방지 SQL 주입 공격은 매개 변수를하는 데 도움이 사용.

    데이터베이스는 데스크탑 프로그램이나 웹 사이트 등의 프로그램 인터페이스와 함께 사용 방지 SQL 주입 공격은 매개 변수를하는 데 도움이 사용.

    당신의 예에서, 사용자가 직접 txtSalary에 문을 공예하여 데이터베이스에 대한 SQL 코드를 실행할 수 있습니다.

    그들이 인 경우 예를 들어, 0 또는 = 1 : 1, 실행 된 SQL이 될 것이다 쓰기

     SELECT empSalary from employee where salary = 0 or 1=1
    

    모든 empSalaries가된다 반환 될 것이다.

    또한, 사용자는 0을 쓴 경우 삭제를 포함하여 데이터베이스에 대해 훨씬 더 명령을 수행 할 수 있습니다; 표 직원을 드롭 :

    SELECT empSalary from employee where salary = 0; Drop Table employee
    

    테이블 직원은 삭제됩니다.

    당신이 .NET을 사용하는 것처럼 귀하의 경우에는, 그것은 보인다. 매개 변수를 사용하면 쉽게 같은과 같다 :

    씨#

    string sql = "SELECT empSalary from employee where salary = @salary";
    
    using (SqlConnection connection = new SqlConnection(/* connection info */))
    using (SqlCommand command = new SqlCommand(sql, connection))
    {
        var salaryParam = new SqlParameter("salary", SqlDbType.Money);
        salaryParam.Value = txtMoney.Text;
    
        command.Parameters.Add(salaryParam);
        var results = command.ExecuteReader();
    }
    

    VB.NET

    Dim sql As String = "SELECT empSalary from employee where salary = @salary"
    Using connection As New SqlConnection("connectionString")
        Using command As New SqlCommand(sql, connection)
            Dim salaryParam = New SqlParameter("salary", SqlDbType.Money)
            salaryParam.Value = txtMoney.Text
    
            command.Parameters.Add(salaryParam)
    
            Dim results = command.ExecuteReader()
        End Using
    End Using
    

    편집 2016년 4월 25일 :

    조지 스토커의 의견에 따라, 나는 AddWithValue을 사용하지 않는 샘플 코드를 변경했습니다. 또한, 일반적으로 당신이 문을 사용하여 IDisposables을 포장하는 것이 좋습니다.

  2. ==============================

    2.당신은 오른쪽이는 malicioius 사용자가 데이터베이스에 대해 임의의 문을 실행할 수있는 취약점입니다 SQL 주입, 관련이있다. 이 옛날 좋아하는 XKCD 만화는 개념을 설명 :

    당신은 오른쪽이는 malicioius 사용자가 데이터베이스에 대해 임의의 문을 실행할 수있는 취약점입니다 SQL 주입, 관련이있다. 이 옛날 좋아하는 XKCD 만화는 개념을 설명 :

    당신의 예에서, 당신은 그냥 사용하는 경우 :

    var query = "SELECT empSalary from employee where salary = " + txtSalary.Text;
    // and proceed to execute this query
    

    당신은 SQL 주입 열려 있습니다. 예를 들어, 말하자면 누군가가 txtSalary를 입력 :

    1; UPDATE employee SET salary = 9999999 WHERE empID = 10; --
    1; DROP TABLE employee; --
    // etc.
    

    이 쿼리를 실행하면, 그들이 원하는대로는 SELECT와 UPDATE 또는 DROP, 또는을 수행합니다. 더 - 끝이 단순히 txtSalary.Text 후 무엇을 연결 한 경우 공격에 유용 할 것이다 쿼리의 나머지 부분을 밖으로 코멘트에서.

    올바른 방법은 매개 변수화 된 쿼리, 예를 들면 (C #)를 사용하는 것입니다 :

    SqlCommand query =  new SqlCommand("SELECT empSalary FROM employee 
                                        WHERE salary = @sal;");
    query.Parameters.AddWithValue("@sal", txtSalary.Text);
    

    그것으로, 당신은 안전하게 쿼리를 실행할 수 있습니다.

    bobby-tables.com을 확인, 여러 다른 언어로 SQL 주입을 방지하는 방법에 대한 참조를 들어, 웹 사이트는 SO 사용자에 의해 유지했다.

  3. ==============================

    3.다른 답변 이외에뿐만 아니라이 SQL 주입을 방지하지만 쿼리의 성능을 향상시킬 수있는 데 도움이 매개 변수를 추가해야합니다. SQL 서버 캐싱은 쿼리 계획을 매개 변수화 반복 쿼리 실행에 재사용. 당신이 당신의 쿼리를 매개 변수화하지 않으면 쿼리의 텍스트가 다를 것입니다 경우 다음 SQL Server는 실행 (일부 제외)와 각 쿼리에 새로운 계획을 컴파일합니다.

    다른 답변 이외에뿐만 아니라이 SQL 주입을 방지하지만 쿼리의 성능을 향상시킬 수있는 데 도움이 매개 변수를 추가해야합니다. SQL 서버 캐싱은 쿼리 계획을 매개 변수화 반복 쿼리 실행에 재사용. 당신이 당신의 쿼리를 매개 변수화하지 않으면 쿼리의 텍스트가 다를 것입니다 경우 다음 SQL Server는 실행 (일부 제외)와 각 쿼리에 새로운 계획을 컴파일합니다.

    쿼리 계획 캐싱에 대한 자세한 정보

  4. ==============================

    4.어떤 단어가 포함되어있는 경우 SQL에서 @ 서명 그것은 변수를 의미하고 변수를 많이 선언 할 수있는 동안 우리는 거기에 설정 값이 변수를 사용하고는 단지 하나의 스크립트에 제한되어 있기 때문에 동일한 SQL 스크립트에 수 영역에서 사용할 많은 스크립트에 동일한 유형 및 이름. 지역 변수, SQL 저장 프로 시저 및 SQL 주입을 선언 읽기 저장 프로 시저가 미리 컴파일 된 쿼리이기 때문에 우리는 저장 프로 시저 주차장에서이 변수를 사용하여 우리는 스크립트, 데스크톱 및 자세한 내용은 웹 사이트에서 이러한 변수에 값을 전달할 수 있습니다.

    어떤 단어가 포함되어있는 경우 SQL에서 @ 서명 그것은 변수를 의미하고 변수를 많이 선언 할 수있는 동안 우리는 거기에 설정 값이 변수를 사용하고는 단지 하나의 스크립트에 제한되어 있기 때문에 동일한 SQL 스크립트에 수 영역에서 사용할 많은 스크립트에 동일한 유형 및 이름. 지역 변수, SQL 저장 프로 시저 및 SQL 주입을 선언 읽기 저장 프로 시저가 미리 컴파일 된 쿼리이기 때문에 우리는 저장 프로 시저 주차장에서이 변수를 사용하여 우리는 스크립트, 데스크톱 및 자세한 내용은 웹 사이트에서 이러한 변수에 값을 전달할 수 있습니다.

    또한 그것은 당신이 당신의 데이터베이스를 보호하는 방법을 안내합니다 SQL 인젝션에서 보호 읽어 보시기 바랍니다.

    당신이 어떤 질문 주석에게도 저를 이해하는 데 도움이 바랍니다.

  5. ==============================

    5.2 년 내 처음으로 이동 후, 나는 recidivating있어 ...

    2 년 내 처음으로 이동 후, 나는 recidivating있어 ...

    왜 우리는 매개 변수를 선호합니까? SQL 주입은 분명히 큰 이유이지만, 우리가 비밀리 언어로 SQL로 돌아갈 갈망 걸 수 있습니다. 문자열 리터럴의 SQL은 이미 이상한 문화적 관행이지만, 적어도 당신은 복사 및 관리 스튜디오에 요청을 붙여 넣을 수 있습니다. SQL은 조건문 및 제어 구조를 가질 때 SQL이 동적 호스트 언어의 조건문과 제어 구조로 구성, 0야만 단지 수준입니다. 당신은 디버그에서 응용 프로그램을 실행하기 위해, 또는 추적하여, SQL이 생성을 확인하려면 다음을 참조하십시오.

    단지 매개 변수를 중단하지 마십시오. 모든 방법을 가서 QueryFirst (면책 조항 : 내가 쓴)를 사용합니다. 당신의 SQL은 .SQL 파일에 살고있다. 당신은 당신의 테이블과 컬럼에 대한 구문 검증 및 인텔리로, 멋진 TSQL 편집기 창에서 편집. 당신은 특별한 코멘트 섹션에서 테스트 데이터를 할당하고 바로 거기 창에서 쿼리를 실행하는 "놀이"를 클릭 할 수 있습니다. 매개 변수를 생성하면 SQL에서 "@myParam"를 두는 것만 큼 쉽습니다. 그런 다음 저장할 때마다, QueryFirst는 쿼리에 대한 C #을 래퍼를 생성합니다. 귀하의 매개 변수는 실행 () 메소드에 인수로서, 강력한 형식의 팝업. 귀하의 결과를 IEnumerable 또는 강력한 형식의 포항 강판의 목록에 반환되는 실제 스키마에서 생성 된 유형은 쿼리에서 반환. 쿼리가 실행되지 않으면, 앱 컴파일되지 않습니다. 당신의 DB 스키마 변경 및 쿼리 실행되지만 일부 열이 사라질 경우, 코드의 라인에 컴파일 에러 포인트는 시도는 누락 된 데이터에 액세스 할 수있다. 그리고 다른 많은 장점이 있습니다. 왜 당신은 데이터에 액세스 할 다른 방법을할까요?

  6. ==============================

    6.매개 변수가 중요한 이유 다른 답변 커버하지만, 단점은있다! .NET에서 매개 변수를 (AddWithValue 추가)를 만들기위한 몇 가지 방법이 있습니다,하지만 그들은 모두 매개 변수 이름에 대해, 불필요하게 걱정에 당신을 필요로, 그들은 모든 코드에서 SQL의 가독성을 줄일 수 있습니다. 당신은 SQL을 묵상하려고 할 때 마우스 오른쪽, 당신은 위의 주위에 사냥을하거나 아래의 매개 변수에 사용 된 어떤 값을 참조 할 필요가있다.

    매개 변수가 중요한 이유 다른 답변 커버하지만, 단점은있다! .NET에서 매개 변수를 (AddWithValue 추가)를 만들기위한 몇 가지 방법이 있습니다,하지만 그들은 모두 매개 변수 이름에 대해, 불필요하게 걱정에 당신을 필요로, 그들은 모든 코드에서 SQL의 가독성을 줄일 수 있습니다. 당신은 SQL을 묵상하려고 할 때 마우스 오른쪽, 당신은 위의 주위에 사냥을하거나 아래의 매개 변수에 사용 된 어떤 값을 참조 할 필요가있다.

    나는 겸손하게 내 작은 SqlBuilder 클래스는 매개 변수가있는 쿼리를 작성하는 가장 우아한 방법입니다 주장한다. 코드는 다음과 같을 것입니다 ...

    씨#

    var bldr = new SqlBuilder( myCommand );
    bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId);
    //or
    bldr.Append("SELECT * FROM CUSTOMERS WHERE NAME LIKE ").FuzzyValue(myName);
    myCommand.CommandText = bldr.ToString();
    

    코드는 더 짧고 더 많은 읽을 수 있습니다. 당신은 당신이 다시 읽을 때, 당신은 매개 변수의 값을 주변에 사냥 할 필요가 없습니다, 별도의 선이 필요하지 않습니다. 당신이 필요로하는 클래스는 여기에 ...

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    
    public class SqlBuilder
    {
    private StringBuilder _rq;
    private SqlCommand _cmd;
    private int _seq;
    public SqlBuilder(SqlCommand cmd)
    {
        _rq = new StringBuilder();
        _cmd = cmd;
        _seq = 0;
    }
    public SqlBuilder Append(String str)
    {
        _rq.Append(str);
        return this;
    }
    public SqlBuilder Value(Object value)
    {
        string paramName = "@SqlBuilderParam" + _seq++;
        _rq.Append(paramName);
        _cmd.Parameters.AddWithValue(paramName, value);
        return this;
    }
    public SqlBuilder FuzzyValue(Object value)
    {
        string paramName = "@SqlBuilderParam" + _seq++;
        _rq.Append("'%' + " + paramName + " + '%'");
        _cmd.Parameters.AddWithValue(paramName, value);
        return this;
    }
    public override string ToString()
    {
        return _rq.ToString();
    }
    }
    
  7. ==============================

    7.이전 게시물 그러나 이민자를 확인하고 싶었다는 저장 프로 시저 알고 있습니다.

    이전 게시물 그러나 이민자를 확인하고 싶었다는 저장 프로 시저 알고 있습니다.

    여기 내 10 ¢의 가치는 당신이 내보기에 최적의 방법이라고, 저장 프로 시저로 SQL 문을 쓸 수있는 경우. 나는 항상 내 주요 코드에 기록을 저장 발동 결코 루프를 사용합니다. SQL 표> SQL 저장 프로 시저> IIS / Dot.NET> 클래스 예를 들면 다음과 같습니다.

    당신이 저장 프로 시저를 사용하는 경우, 따라서 보안 위험을 감소, 전용 권한을 실행할 수있는 사용자를 제한 할 수 있습니다.

    귀하의 저장 프로 시저가 본질적으로 paramerised, 당신은 입력 및 출력 매개 변수를 지정할 수 있습니다.

    저장 프로 시저는 (은 SELECT 문을 통해 데이터를 반환하는 경우) 액세스와 동일한 방법으로 읽을 수와 같이 코드에서 일반 SELECT 문 것.

    그것이 SQL 서버에서 컴파일 그것은 또한 빠르게 실행됩니다.

    또한, 예를 들어, 여러 단계를 수행 할 수 있습니다 언급 했 같은 서버 및 클라이언트와의 상호 작용없이 모든 클라이언트에 반환 데이터를 다른 DB 서버에 값을 확인하고 한 번 마지막으로 완성, 테이블을 업데이트합니다. 그래서이 훨씬 더 빠르게 코드에서이 논리를 코딩보다.

  8. from https://stackoverflow.com/questions/7505808/why-do-we-always-prefer-using-parameters-in-sql-statements by cc-by-sa and MIT license